Check a condition within a foreach in scala - scala

Is there a way to check a condition within a foreach loop in scala. The example is that I want to go through an array of integers and do some arbitrary math on the positive numbers.
val arr = Array(-1,2,3,0,-7,4) //The array
//What I want to do but doesn't work
arr.foreach{if(/*This condition is true*/)
{/*Do some math and print the answer*/}}
//Expected answer for division by six is 0.333333333 \n 0.5 \n 0.666666667
//Which is 2/6, 3/6 and 4/6 respectively as they appear in the array
I know how to do it with a normal for loop and if statement but I want to use this because I want to get away from java.
Thanks

foreach function brings every item in the list/array one by one, you should set it to a variable before to use it.
For example:
arr.foreach( variable_name => {
if(/*This condition is true*/){
/*Do some math and print the answer*/
}
})

The argument to foreach is a function, taking one argument, and returning a Unit. The argument is current element of the list, as it has been pointed out in other answers. You can just give it a name, and reference it as you would any other variable.
arr.foreach { x => if(x > 0) println(x/6.0) }
It is generally better and more idiomatic to split your logic into a chain of simpler "atomic" transformations rather than putting everything into one long function:
arr
.iterator
.filter(_ > 0)
.map(_ / 6.0)
.foreach(println)
The underscore _ above is shorthand for the function argument. You can use it in short functions when you only need to reference the argument once, and a few other conditions are satisfied. The last line doesn't need to pass the argument to println, because println itself is a function, being passed to foreach. I could write it as .foreach(println(_)) or .foreach(x => println(x)), it would do the same thing, but is technically a little different: this form creates an anonymous function like def foo(x: Double) { println(x) } and passes it to foreach as an argument, the way I wrote it originally, just passes println itself as an argument.
Also, note a call to .iterator in the beginning. Everything would work the same way if you take it out. The difference is that iterators are lazy. The way it is written, the code will take first argument from the array, send it through filter, if it returns false, it'll stop, and go back to the second element, if filter returns true, it'll send that element to map, then print it out, then go back, grab the next element etc.
Without .iterator call, it'd work differently: first, it would run the entire array through filter, and create a new array, containing only positive numbers, then, it'd run that new array through map, and create a new one, with the numbers divided by 6, then it'd go through this last array to print out the values. Using .iterator makes it more efficient by avoiding all the intermediate copies.

First, you'll want to use map() instead of foreach() because map() returns a result whereas foreach() does not and can only be used for side effects (which should be avoided when possible).
As has been pointed out, you can filter() before the map(), or you can combine them using collect().
arr.collect{case x if x > 0 => x/6.0}
// res0: Array[Double] = Array(0.3333333333333333, 0.5, 0.6666666666666666)

Use the filter function before using the foreach.
arr.filter(_ > 0).foreach { value => ... }

var list: ListSet[Int] = ListSet(-1, -5, -3, 8, 7, 9, 4, 6, 2, 1, 0)
list.filter(p => p > 5).foreach(f => {
print(f + " ")
})
Output : 8 7 9 6

Just do a filter and a map.
Don't forget that scala consider the array you want as Array[Int], so if you apply /6, you gonna have 0, ensure the cast by add .toDouble
val arr = Array(-1,2,3,0,-7,4)
val res = arr.filter(_>0).map(_.toDouble/6)
res.foreach(println)
Result:
0.3333333333333333
0.5
0.6666666666666666

Related

Filtering a Scala List

I need to create function that takes double and returns new list, based on the first one, that includes absolute values of elements grom the first list that belongs to the range of <-5,12>. I need to use filtering. I have an idea, but it's not working. I'm sorry, maybe my question is easy, but I'm a begginer :)
var numbersReal = List(2.25, -1, -3, 7.32, 0.25, -6, 0, 2, 0, 1, 0, 2.99, 3.02, 0)
def magicFilter(list: List[Double]): List[Double] = {
var newList = List[Double]()
list.foreach {element => if (-5 <= element && element <= 12) newList += scala.math.abs(element) }
newList.toList
}
println(magicFilter(numbersReal))
Best Practice Solution
You can do this easily with a combination of
filter: keep only elements that satisfy a given predicate / condition. For us, it will be keeping only elements in [-5,12]
map: apply a function to every element. For us, it will be taking the absolute value.
numbersReal.filter(e => e >= -5 && e <= 12).map(math.abs)
Another way to achieve this in "one-shot" is to use collect which combines both filter and map:
numbersReal.collect { case e if e >= 5 && e <= 12 => math.abs(e) }
I personally find the first solution to be more readable in this particular case, but that's a matter of opinion.
Usually, these problems can be solved without resorting to a var or any mutable collection. Scala's collections are one of its greatest assets because they include a lot of these primitive operations, and most problems can be solved by combining them.
Note regarding your proposed solution
Your solution is not wrong per-se, but it is very error-prone to implement logic that is already part of collection methods like filter, map and collect. If you wanted to fix your approach, you just have to replace newList += ... with newList :+= .... This is because adding an element to an immutable List is done with list :+ element (or element +: list if you want to prepend). The list :+= element is syntactic sugar for list = list :+ element. Again, these are not constructs you should encounter very often, because this style is generally frowned-upon except if you know you have a very good reason to use mutability.

Scala - Use of .indexOf() and .indexWhere()

I have a tuple like the following:
(Age, List(19,17,11,3,2))
and I would like to get the position of the first element where their position in the list is greater than their value. To do this I tried to use .indexOf() and .indexWhere() but I probably can't find exactly the right syntax and so I keep getting:
value indexWhere is not a member of org.apache.spark.rdd.RDD[(String,
Iterable[Int])]
My code so far is:
val test =("Age", List(19,17,11,3,2))
test.indexWhere(_.2(_)<=_.2(_).indexOf(_.2(_)) )
I also searched the documentation here with no result: http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.List
If you want to perform this for each element in an RDD, you can use RDD's mapValues (which would only map the right-hand-side of the tuple) and pass a function that uses indexWhere:
rdd.mapValues(_.zipWithIndex.indexWhere { case (v, i) => i+1 > v} + 1)
Notes:
Your example seems wrong, if you want the last matching item it should be 5 (position of 2) and not 4
You did not define what should be done when no item matches your condition, e.g. for List(0,0,0) - in this case the result would be 0 but not sure that's what you need

Scala, collections, variable access scope

Sorry, I got even no idea how to name a title, as I believe this is a dead simple thing.
I have function which is taking Int as an argument and returning List of Ints (after adding values to int trough loop, and couple if statements. Signature is a must)
My problem:
def a(i:Int) = { var l2 = List(1,2); l2.+:(1); l2; }
println(a(3)) // outputs List(1, 2)
Why function a is returning List(1,2) instead of List(3,1,2) ??
And what would be a correct solution in this situation?
I really appreciate your time to help me.
The method +: that you are calling on a List returns a new list with the element prepended. The original list is not modified.
In the statement l2.+:(1) you are ignoring the return value (the new list with the element prepended). Then you return l2, which still refers to the original List which contains the two elements 1 and 2.
You are missing an assignment (and you probably meant i instead of 1): l2 +:= i.
But in scala it is preferable to avoid using var:
def a(i: Int) = { i :: List(1, 2) }
(I guess your method is much more complex, but it's almost always possible to rewrite it that way)

Constructing a lambda expression using an underscore

This code
(1 to 30).foreach { x =>
println(x)
println
}
does what I'd expect: it prints each of 1 to 30, interspersed with blanks. I'm pretty clear on what's going on here, I think: I'm passing an anonymous function that first prints its argument, and then prints a blank line.
What I don't understand is why this doesn't do the same:
(1 to 30).foreach {
println _
println
}
It looks equivalent to me. The underscore should represent the first and only argument to the function; and the function prints its argument, and then prints a blank line. But when I run this second version, I don't get the blank lines.
What causes this difference?
The first variant is straightforward:
In the first line, apply println on x.
In the second line, apply the no-argument println (this prints the extra newline).
With the second variant you effectively tell Scala to do this:
In the first line, define a function object from println().
Subsequently, do nothing with this newly created object.
In the second line, apply println to the argument (the element of the
sequence).
The confusion stems from the assumption that println(x) and println _ are equivalent. They are different. The funcId _ syntax defines a new function based on funcId, it is not the same as using the "underscore argument" notation when calling a function.
There is a number of things going on here.
First, of all the parameter placeholder syntax can only be used within outer parentheses of the lambda definition. It cannot be used within parentheses of the method calls that you perform within the lambda definition.
Here is an example to demonstrate this point.
val a = (1 to 10).map(_ + 1)
This will work.
val b = (1 to 10).map(math.sin(_ + 1))
This will not work.
Therefore your code does not use parameter placeholder syntax at all. It instead uses partially applied functions.
For example
(1 to 10).foreach(println _)
is functionally equal to
val a = println (_ : Int)
(1 to 10).foreach(a)
Also when a method name is used within lambda expression the underscore can be omitted. Scala will still generate the partially applied method.
Therefore
(1 to 10).foreach(println)
is equal to
(1 to 10).foreach(println _)
And therefore your code is equal to
val a = println (_ : Int)
(1 to 10).foreach{
a
a
}
And because {a a} returns a, it is equal to
val a = println (_ : Int)
(1 to 10).foreach(a)
To add to other answers, there actually exists a way to use println(_) and not to declare x parameter:
(1 to 30).foreach {
println(_: Int)
println
}
Here foreach parameter is function, which firstly invokes println(_) for range element, and then passes println(Int) result (which is (): Unit) to another function, _ => println, which ignores it's argument and prints new line.

scala: accumulate a var from collection in a functional manner (that is, no vars)

this is a newbie question
I have the following code:
var total = 0L
docs.foreach(total += _.length)
in docs I have a collection of objects with the .length property
I'd like something like:
val total = docs.[someScalaMethod](0, (element, acum) => acum + element.length )
I mean, a method that iterates each element passing an accumulator variable...
The first zero I pass should be the initial value of the accumulator var..
How can it be achieved?
This called a fold. It's almost exactly what you stated:
docs.foldLeft(0)((accum, element) => accum + element.length)
for the version that traverses the collection from left to right (usually preferable; right to left is foldRight, and 2.9 has a fold that can start anywhere, but has limitations on how it can transform the type).
Once you get used to this, there is a short-hand version of fold left, where the accumulator goes on the left (think of it being pushed from left to right through the list), and you use placeholders for the variable names since you only use them once each: (0 /: docs)(_ + _.length)
docs map { _.length } reduce { _ + _ }
or (the thx goes to Luigi Plinge)
docs.map(_.length).sum
Here is a Scalaz version:
docs.foldMap(_.length)
This is equivalent to docs.map(_.length).sum but takes only one pass. Also, works with all monoids.