Reputation: 4452
I'm learning Scala now, and I have a scenario where I have to compare an element (say num
) with all the elements in a list.
Assume,
val MyList = List(1, 2, 3, 4)
If num
is equal to anyone the elements in the list, I need to return true
. I know to do it recursively using the head
and tail
functions, but is there a simpler way to it (I think I'll be able to do it using foreach
, but I'm not sure how to implement it exactly)?
Upvotes: 0
Views: 2628
Reputation: 62835
There is number of possibilities:
val x = 3
MyList.contains(x)
!MyList.forall(y => y != x) // early exit, basically the same as .contains
If you plan to do it frequently, you may consider to convert your list to Set, cause every .contains
lookup on list in worst case is proportional to number of elements, whereas on Set it is effectively constant
val mySet = MyList.toSet
mySet.contains(x)
or simply:
mySet(x)
Upvotes: 10
Reputation: 103777
As others have answered, the contains
method on the list will do exactly this, and it's the most understandable/performant way.
Looking at your closing comments though, you wouldn't be able to do it (in an elegant fashion) with foreach
, since that returns Unit
. Foreach "does" something for each element, but you don't get any result back. It's useful for logging/println statements, but it doesn't act as a transformation.
If you want to run a function on every element individually, you would use map
, which returns a List of the results of applying the function. So assuming num = 3, then MyList.map(_ == num)
would return List(false, false, true, false)
. Since you're looking for a single result, and not a list of results, then this is not what you're after.
In order to collapse a sequence of things into a single result, you would use a fold over the data. Folding involves a function that takes two arguments (the result so far, and the current thing in the list) and returns the new running result. So that this can work on the very first element, you also need to provide the initial value to use for the ongoing result (usually some sort of zero).
In your particular case, then, you want a Boolean
answer at the end - "was an element found that was equal to num
". So the running result would be "have I seen an element so far that was equal to num
". Which means the initial value is false
. And the function itself should return true
if an element has already been seen, or if the current element is equal to num
.
Putting this together, it would look like this:
MyList.foldLeft(false) { case (runningResult, listElem) =>
// return true if runningResult is true, or if listElem is the target number
runningResult || listElem == num
}
This doesn't have the nice aspect of stopping as soon as the target value has been found - and it's nowhere near as concise as calling MyList.contains
. But as an instructional example, this is how you could implement this yourself from the primitive functional operations on a list.
Upvotes: 3
Reputation: 19167
A contains
method is pretty standard for lists in any language. Scala's List
has it too:
http://www.scala-lang.org/api/current/scala/collection/immutable/List.html
Upvotes: 3