takeWhile: also need first element failed the condition in scala - scala

scala> List(1,2,3,4,5,6,7).takeWhile(i=>i<5)
res1: List[Int] = List(1, 2, 3, 4)
What if I also need to include 5 in the result?

Assuming that the function that you will be using is more complicated than the taking first 5 elements then,
You can do
scala> List(1,2,3,4,5,6,7)
res5: List[Int] = List(1, 2, 3, 4, 5, 6, 7)
scala> res5.takeWhile(_<5) ++ res5.dropWhile(_<5).take(1)
res7: List[Int] = List(1, 2, 3, 4, 5)
Also
scala> res5.span(_<5)
res8: (List[Int], List[Int]) = (List(1, 2, 3, 4),List(5, 6, 7))
scala> res8._1 ++ res8._2.take(1)
res10: List[Int] = List(1, 2, 3, 4, 5)
Also
scala> res5.take(res5.segmentLength(_<5, 0) + 1)
res17: List[Int] = List(1, 2, 3, 4, 5)
scala> res5.take(res5.indexWhere(_>5))
res18: List[Int] = List(1, 2, 3, 4, 5)

Edit
If this is not a parallelized computation and you won't be using the parallel collections:
var last = myList.head
val rem = myList.takeWhile{ x=>
last = x
x < 5
}
last :: rem
anonymous function forming a closure around the solution you want.
Previous Answer
I'd settle for the far less complicated:
.takeWhile(_ <= 5)
wherein you're just using the less than or equal operator.

List(1,2,3,4,5,6,7,8).takeWhile(_ <= 5)
This is best optimal solution for it

Related

Scala .init method example

Can you please explain what init method performs with respect to below list
i can see the result of new list says that last sequence is being omitted from the existing list.
val numbers = List(1, 2, 3, 4, 5)
val result = numbers.init
println(result)
.init and .last are the compliments to the .head and .tail methods.
val nums = List(1,2,3,4)
nums.head //res0: Int = 1
nums.tail //res1: List[Int] = List(2, 3, 4)
nums.init //res2: List[Int] = List(1, 2, 3)
nums.last //res3: Int = 4
def init: List[A] which selects all elements except the last.
l: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8)
scala> l.last
res58: Int = 8
scala> l.init
res59: List[Int] = List(1, 2, 3, 4, 5, 6, 7)
scala> val testList = List(1,2,3,4,5)
testList: List[Int] = List(1, 2, 3, 4, 5)
scala> testList.init
res0: List[Int] = List(1, 2, 3, 4)
scala> testList.last
res1: Int = 5
scala> testList.head
res2: Int = 1
scala> testList.tail
res3: List[Int] = List(2, 3, 4, 5)

why does sameElements returns true for sets?

Why sameElements returned true for sets? Sets do not put elements in any order. In following two examples, the first one returns true but the second one returns false.
scala> val xs1 = Set(3, 2, 1, 4, 5, 6, 7)
xs1: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 7, 3, 4)
scala> val ys1 = Set(7, 2, 1, 4, 5, 6, 3)
ys1: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 7, 3, 4)
scala> xs1 sameElements ys1
res7: Boolean = true
scala> val xt1 = Set(1, 2, 3)
xt1: scala.collection.immutable.Set[Int] = Set(1, 2, 3)
scala> val yt1 = Set(3, 2, 1)
yt1: scala.collection.immutable.Set[Int] = Set(3, 2, 1)
scala> xt1 sameElements yt1
res8: Boolean = false
For scala.collection.immutable.Set.sameElements(Set) to return true, both sets need to have the same elements, in the same order.
The default Set implementations are not ordered, so the element ordering depends upon the storage algorithm and the order in which elements were added. In your first example, the ordering turned out to be the same purely by coincidence.
If you use a scala.collection.immutable.SortedSet instead, you should get what you expect.
EDIT: If you want to just check whether two sets contain the same elements, regardless of order, just use equals. To illustrate this, try the following:
scala> val xt1 = Set(1, 2, 3)
xt1: scala.collection.immutable.Set[Int] = Set(1, 2, 3)
scala> val yt1 = Set(3, 2, 1)
yt1: scala.collection.immutable.Set[Int] = Set(3, 2, 1)
scala> xt1 sameElements yt1
res0: Boolean = false
scala> xt1 == yt1
res1: Boolean = true
So sameElements is useful if you need to determine whether the ordering is the same as well as the elements themselves; otherwise, just use good ole ==.

partition an Array with offset

in Clojure I can partition a vector with offset step like
(partition 2 1 [1 2 3 4])
this returns a sequence of lists of n items each at offsets step apart.
for example the previous method returns
((1 2) (2 3) (3 4))
I just wonder how can I acheive the same in Scala
use sliding - Array(1, 2, 3, 4).sliding(2). This would give you an Iterator and you can just call e.g. toArray and get Array[Array[Int]] where internals are as desired.
There is function in the standard library sliding for this purpose
scala> val x = Array(1, 2, 3).sliding(2, 1)
x: Iterator[Array[Int]] = non-empty iterator
scala> x.next
res8: Array[Int] = Array(1, 2)
scala> x.next
res9: Array[Int] = Array(2, 3)
scala> val l = List(1, 2, 3, 4, 5)
l: List[Int] = List(1, 2, 3, 4, 5)
scala> l.sliding(2).toList
res0: List[List[Int]] = List(List(1, 2), List(2, 3), List(3, 4), List(4, 5))
I think this does what you need:
List(1,2,3,4).sliding(2,1).toList

Complement method for .last when working with List objects?

Working with Lists in Scala I would like a simple way to get all elements but the last element. Is there a complementary method for .last similar to .head/.tail complement?
I'd rather not dirty up code with something like:
val x: List[String] = List("abc", "def", "ghi")
val allButLast: List[String] = x.reverse.tail.reverse
// List(abc, def)
Thanks.
init selects all elements but the last one.
List API for init.
scala> List(1,2,3,4,5)
res0: List[Int] = List(1, 2, 3, 4, 5)
scala> res0.init
res1: List[Int] = List(1, 2, 3, 4)
The 4 related methods here are head, tail, init, and last.
head and last get the first and final member, whereas
tail and init exclude the first and final members.
scala> val list = (0 to 10).toList
list: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
scala> list.head
res0: Int = 0
scala> list.tail
res1: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
scala> list.init
res2: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
scala> list.last
res3: Int = 10
You should also take care, because all 4 of them are unsafe on the empty list and will throw exceptions.
These methods are defined on GenTraversableLike, which List implements.
That's init.
link to Scaladoc: http://www.scala-lang.org/api/2.11.5/index.html#scala.collection.immutable.List#init:Repr
def init: List[A]
Selects all elements except the last.
Also, note that it's defined in GenTraversableLike, so pretty much any Scala collection has this method.
For dropping off any number of items from the end of a list consider dropRight,
val xs = (1 to 5).toList
xs.dropRight(1)
List(1, 2, 3, 4)
xs.dropRight(2)
List(1, 2, 3)
xs.dropRight(10)
List()

Concise notation for single arg anonymous function (avoiding underscore) not working as expected

After going through some examples on the web I realize that there is a way to write an anonymous function without the underscore when only a single arg. Also, I'm experimenting with the "span" method on List, which I never knew existed. Anyway, here is my REPL session:
scala> val nums = List(1, 2, 3, 4, 5)
nums: List[Int] = List(1, 2, 3, 4, 5)
scala> nums span (_ != 3)
res0: (List[Int], List[Int]) = (List(1, 2),List(3, 4, 5))
scala> nums span (3 !=)
res1: (List[Int], List[Int]) = (List(1, 2),List(3, 4, 5))
So far so good. But when I try to use the "less than" operator:
scala> nums span (_ < 3)
res2: (List[Int], List[Int]) = (List(1, 2),List(3, 4, 5))
scala> nums span (3 <)
res3: (List[Int], List[Int]) = (List(),List(1, 2, 3, 4, 5))
Why is this behaving differently?
scala> nums span (_ < 3)
res0: (List[Int], List[Int]) = (List(1, 2),List(3, 4, 5))
scala> nums span (3 >)
res1: (List[Int], List[Int]) = (List(1, 2),List(3, 4, 5))
3 < is a shortcut to 3 < _, which creates a partially applied function from method call.
It's behaving correctly:
scala> nums span (3 < _)
res4: (List[Int], List[Int]) = (List(),List(1, 2, 3, 4, 5))
The predicate is false for the first element of the list, so the first list returned by span is empty.
scala> nums span (3 < _)
res0: (List[Int], List[Int]) = (List(),List(1, 2, 3, 4, 5))
// is equivalent to
scala> (nums takeWhile{3 < _}, nums.dropWhile{3 < _})
res1: (List[Int], List[Int]) = (List(),List(1, 2, 3, 4, 5))
where
the predicate is false already for the first element(1) therefore nums.takeWhile{false} results in the empty list List()
For the second part nothing is dropped because the predicate is false already for the first
element(1) and therefore the nums.dropWhile{false} is the whole list List(1, 2, 3, 4, 5).