takeWhile in Scala for element n+1 - list

Define the function dropWhileSmallerThanFive, it should take a list and discard the first n elements, until the next element (n+1) is greater or equal to 5.
*Use one of Scala's built-in list functions (e.g. takeWhile).
I tried this:
def dropWhileSmallerThanFive(xs: List[Int]): List[Int] = xs match {
case Nil => Nil
case head :: b :: tail if b >= 5 => head :: (b::tail).takeWhile(_>=5)
case _ => Nil
}
But it's completly wrong, what should I do?

Welcome to SO! If you are new to Scala, consider the following beginner-friendly resources
Real-time help: gitter.im/scala/scala
Interactive exercises: scala-exercises.org
Tour of Scala: docs.scala-lang.org/tour/tour-of-scala.html
Hello world template: sbt new scala/scala-seed.g8
Online interactive playground: scastie.scala-lang.org
Scala provides List.dropWhile out-of-the-box, or consider the following recursive implementation
def recDropWhile(l: List[Int], predicate: Int => Boolean): List[Int] = {
#scala.annotation.tailrec
def loop(l: List[Int], predicate: Int => Boolean): List[Int] = {
l match {
case Nil => Nil
case head :: tail => if (predicate(head)) loop(tail, predicate) else (head :: tail)
}
}
loop(l, predicate)
}
Both output
val l = List(1,2,3,4,5,6,7,8)
l.dropWhile(_ < 5) // res3: List[Int] = List(5, 6, 7, 8)
recDropWhile(l, _ < 5) // res4: List[Int] = List(5, 6, 7, 8)

Related

Scala: slice a list from the first non-zero element

Suppose I have a list filled with zeroes
val a = List(0,0,0,0,2,4,0,6,0,7)
I want to slice away the zeroes preceding the first non-zero element and also return the index where the 1st non-zero element is present.
Foe the above case I want an output:
output = List(2,4,0,6,0,7)
idx = 4
How do I do it?
First, you can use zipWithIndex to conveniently pair each element with its index. Then use dropWhile to return all of the preceding zero elements. From there, you'll have all of the remaining elements paired with their indices from the original List. You can unzip them. Since this may result in an empty list, the index you're looking for should be optional.
scala> val (remaining, indices) = a.zipWithIndex.dropWhile { case (a, i) => a == 0 }.unzip
remaining: List[Int] = List(2, 4, 0, 6, 0, 7) // <--- The list you want
indices: List[Int] = List(4, 5, 6, 7, 8, 9)
scala> val index = indices.headOption
index: Option[Int] = Some(4) // <--- the index of the first non-zero element
This is a use-case for span:
val a = List(0,0,0,0,2,4,0,6,0,7)
val (zeros, output) = a.span(_ == 0)
val idx = zeros.length
use dropWhile:
val output = a.dropWhile{ _ == 0 }
val idx = output.headOption
.map(_ => a.length - output.length)
.getOrElse(-1) // index starting from 0, -1 if not found
Sightly modified from #bottaio answer, but returning an Option[Int] instead of a plain Int for the index.
def firstNonZero(l: List[Int]): (Option[Int], List[Int]) = {
#annotation.tailrec
def go(remaining: List[Int], idx: Int): (Int, List[Int]) =
remaining match {
case Nil => idx -> Nil
case 0 :: xs => go(remaining = xs, idx + 1)
case xs => idx -> xs
}
l match {
case 0 :: xs =>
val (idx, list) = go(remaining = xs, idx = 1)
Some(idx) -> list
case list =>
None -> list
}
}
Just another solution using foldLeft:
val (i, l) =
a.foldLeft((None: Option[Int], List.empty: List[Int]))((b, n) => {
if (n == 0 && b._2.isEmpty) (b._1.orElse(Some(0)).map(_ + 1), List.empty)
else (b._1.orElse(Some(0)), b._2 :+ n)
})
i: Option[Int] = Some(4)
l: List[Int] = List(2, 4, 0, 6, 0, 7)
You can do it pretty clean with indexWhere:
val idx = a.indexWhere(_!=0)
val output = a.drop(idx)
Others have provided answers that requires multiple list traversals. You can write a recursive function to calculate that in a single pass:
def firstNonZero(l: List[Int]): (Int, List[Int]) = {
#tailrec
def go(l: List[Int], idx: Int): (Int, List[Int]) = l match {
case Nil => (idx, Nil)
case 0 :: xs => go(xs, idx + 1)
case xs => (idx, xs)
}
go(l, 0)
}
what is also equivalent to
val (leadingZeros, rest) = a.span(_ == 0)
val (index, output) = (leadingZeros.length, rest)

How to extend a Scala list to enable slicing not by explicit position but by given predicate/condition

For
trait Item
case class TypeA(i: Int) extends Item
case class TypeB(i: Int) extends Item
consider a Scala list of items such as
val myList = List(TypeA(1), TypeB(11), TypeB(12),
TypeA(2), TypeB(21),
TypeA(3), TypeB(31))
The goal is to define a new slice method that can be applied onto myList and which takes a predicate or condition as argument; for instance
myList.slice { x => x.isInstanceOf[TypeA] }
would deliver
List(List(TypeA(1), TypeB(11), TypeB(12)),
List(TypeA(2), TypeB(21)),
List(TypeA(3), TypeB(31)))
In this example, an identical result would be achieved by
myList.slice { case TypeA(x) => x < 10 }
Many Thanks.
List already has a slice method - it takes a subset of elements between a start and end index. What you're looking for is repeated application of the span method:
def span(p: (A) ⇒ Boolean): (List[A], List[A])
Which is documented as:
Splits this list into a prefix/suffix pair according to a predicate.
Note: c span p is equivalent to (but possibly more efficient than) (c takeWhile p, c dropWhile p), provided the evaluation of the predicate p does not cause any side-effects.
returns: a pair consisting of the longest prefix of this list whose elements all satisfy p, and the rest of this list.
You can get what you need by repeatedly using this method with an inverse predicate, and an extra bit of logic to ensure that none of the returned Lists are empty.
import annotation.tailrec
def multiSpan[A](xs: List[A])(splitOn: (A) => Boolean): List[List[A]] = {
#tailrec
def loop(xs: List[A], acc: List[List[A]]) : List[List[A]] = xs match {
case Nil => acc
case x :: Nil => List(x) :: acc
case h :: t =>
val (pre,post) = t.span(!splitOn(_))
loop(post, (h :: pre) :: acc)
}
loop(xs, Nil).reverse
}
UPDATE
As requested in comments on the original post, here's a version that enriches list instead of being a standalone method:
implicit class AddMultispanToList[A](val list: List[A]) extends AnyVal {
def multiSpan(splitOn: (A) => Boolean): List[List[A]] = {
#tailrec
def loop(xs: List[A], acc: List[List[A]]) : List[List[A]] = xs match {
case Nil => acc
case x :: Nil => List(x) :: acc
case h :: t =>
val (pre,post) = t.span(!splitOn(_))
loop(post, (h :: pre) :: acc)
}
loop(list, Nil).reverse
}
}
Use as:
myList.multiSpan(_.isInstanceOf[TypeA])
Why couldn't you use partition method from the standard API?
example:
scala> val l = List(3,5,4,6)
l: List[Int] = List(3, 5, 4, 6)
scala>
scala> val (odd,even) = l.partition(_ %2 ==1)
odd: List[Int] = List(3, 5)
even: List[Int] = List(4, 6)
For your example:
scala> val (typeA,typeB) = myList.partition(_.isInstanceOf[TypeA])
typeA: List[Product with Serializable with Item] = List(TypeA(1), TypeA(2), TypeA(3))
typeB: List[Product with Serializable with Item] = List(TypeB(11), TypeB(12), TypeB(21), TypeB(31))
Aren't you looking for filter, which works (almost) without any tweaks for your examples?
$ sbt console
scala> trait Item
scala> case class TypeA(i: Int) extends Item
scala> case class TypeB(i: Int) extends Item
scala> val myList = List(TypeA(1), TypeB(11), TypeB(12),
TypeA(2), TypeB(21),
TypeA(3), TypeB(31))
myList: List[Product with Serializable with Item] = List(TypeA(1), TypeB(11), TypeB(12), TypeA(2), TypeB(21), TypeA(3), TypeB(31))
your first works unaltered:
scala> myList.filter { x => x.isInstanceOf[TypeA] }
res0: List[Product with Serializable with Item] = List(TypeA(1), TypeA(2), TypeA(3))
your second requires a default case:
scala> myList.filter { case TypeA(x) => x < 10; case _ => false }
res2: List[Product with Serializable with Item] = List(TypeA(1(3))
See also collect, which takes a partial function instead of a boolean predicate:
scala> myList.collect { case z # TypeA(x) if x < 10 => z }
res3: List[TypeA] = List(TypeA(1), TypeA(2), TypeA(3))
and can transform as well:
scala> myList.collect { case TypeA(x) if x < 10 => x }
res4: List[Int] = List(1, 2, 3)

Split list into multiple lists with fixed number of elements

How to split a List of elements into lists with at most N items?
ex: Given a list with 7 elements, create groups of 4, leaving the last group possibly with less elements.
split(List(1,2,3,4,5,6,"seven"),4)
=> List(List(1,2,3,4), List(5,6,"seven"))
I think you're looking for grouped. It returns an iterator, but you can convert the result to a list,
scala> List(1,2,3,4,5,6,"seven").grouped(4).toList
res0: List[List[Any]] = List(List(1, 2, 3, 4), List(5, 6, seven))
There is much easier way to do the task using sliding method.
It works this way:
val numbers = List(1, 2, 3, 4, 5, 6 ,7)
Lets say you want to break the list into smaller lists of size 3.
numbers.sliding(3, 3).toList
will give you
List(List(1, 2, 3), List(4, 5, 6), List(7))
Or if you want to make your own:
def split[A](xs: List[A], n: Int): List[List[A]] = {
if (xs.size <= n) xs :: Nil
else (xs take n) :: split(xs drop n, n)
}
Use:
scala> split(List(1,2,3,4,5,6,"seven"), 4)
res15: List[List[Any]] = List(List(1, 2, 3, 4), List(5, 6, seven))
edit: upon reviewing this 2 years later, I wouldn't recommend this implementation since size is O(n), and hence this method is O(n^2), which would explain why the built-in method becomes faster for large lists, as noted in comments below. You could implement efficiently as follows:
def split[A](xs: List[A], n: Int): List[List[A]] =
if (xs.isEmpty) Nil
else (xs take n) :: split(xs drop n, n)
or even (slightly) more efficiently using splitAt:
def split[A](xs: List[A], n: Int): List[List[A]] =
if (xs.isEmpty) Nil
else {
val (ys, zs) = xs.splitAt(n)
ys :: split(zs, n)
}
I am adding a tail recursive version of the split method since there was some discussion of tail-recursion versus recursion. I have used the tailrec annotation to force the compiler to complain in case the implementation is not indeed tail-recusive. Tail-recursion I believe turns into a loop under the hood and thus will not cause problems even for a large list as the stack will not grow indefinitely.
import scala.annotation.tailrec
object ListSplitter {
def split[A](xs: List[A], n: Int): List[List[A]] = {
#tailrec
def splitInner[A](res: List[List[A]], lst: List[A], n: Int) : List[List[A]] = {
if(lst.isEmpty) res
else {
val headList: List[A] = lst.take(n)
val tailList : List[A]= lst.drop(n)
splitInner(headList :: res, tailList, n)
}
}
splitInner(Nil, xs, n).reverse
}
}
object ListSplitterTest extends App {
val res = ListSplitter.split(List(1,2,3,4,5,6,7), 2)
println(res)
}
I think this is the implementation using splitAt instead of take/drop
def split [X] (n:Int, xs:List[X]) : List[List[X]] =
if (xs.size <= n) xs :: Nil
else (xs.splitAt(n)._1) :: split(n,xs.splitAt(n)._2)

Accessing the next element in list to compare in Scala

I'm new to Scala and i was wondering how you can call the next element of the list because I am trying to compare the current element with the adjacent one.
Given x as the current element, I tried similar to java, x+1 but that didnt work. Any help?
for (x <- list; if (x == (next adj. element))) println("same")
How about sliding?
val list = List(1,2,3,4)
list.sliding(2).foreach(println)
//List(1, 2)
//List(2, 3)
//List(3, 4)
The canonical ways to do this in a for loop would be:
scala> val xs = List(1,2,3,4,3,2)
xs: List[Int] = List(1, 2, 3, 4, 3, 2)
scala> for (List(left,right) <- xs.sliding(2) if (left < right)) println(left + " < " + right)
1 < 2
2 < 3
3 < 4
scala> for ((left,right) <- (xs zip xs.tail) if (left < right)) println(left + " < " + right)
1 < 2
2 < 3
3 < 4
(Incidentally, you're probably better off putting the if statement outside rather than inside the for comprehension in this example.)
If you have indices instead of values, you just dereference them using the same pattern. Personally, I don't find this pattern very clear or useful. It's slow, has weird corner-cases with lists that aren't full, and it's hard to follow what's going on. Instead, I define
class PairedIterable[A](it: Iterable[A]) {
def foreachpair(f: (A,A) => Unit) = {
val i = it.iterator
if (i.hasNext) {
var prev = i.next
while (!ans && i.hasNext) {
val x = i.next
f(prev,x)
prev = x
}
}
}
}
implicit def iterable_has_pairs[A](it: Iterable[A]) = new PairedIterable(it)
which can then be used like so:
scala> xs.foreachpair((left, right) => if (left < right) println(left + " < " + right))
1 < 2
2 < 3
3 < 4
Variants "forallpair", "existspair", and "findpair" are particularly useful.
scala> val xs = 1::3::5::4::Nil
xs: List[Int] = List(1, 3, 5, 4)
scala> (xs, xs.tail).zip.foreach(println)
(1,3)
(3,5)
(5,4)
scala>
As an option you may use match and recursion instead of for:
object Test {
def main(args: Array[String]) {
val list = List(1, 5, 3)
loop(list)
}
def loop(list: List[Int]) {
list match {
case Nil => println("Empty list")
case x :: Nil => println("last " + x)
case x :: tail => {
println(x + " - " + tail.head)
loop(tail)
}
}
}
}
This would be better handled by recursing over the list, instead of iterating through the elements, since elements don't know anything about the list.
For example:
def recurse[T](list: List[T]): Unit = list match {
case List(x, y, _*) if x == y =>
println("same")
recurse(list.tail)
case Nil =>
case _ => recurse(list.tail)
}
As in Scala 2.11.7 the following are valid:
scala> val xs = List(1,2,3,4)
xs: List[Int] = List(1, 2, 3, 4)
1) Zip the tail
scala> xs.zip(xs.tail)
res0: List[(Int, Int)] = List((1,2), (2,3), (3,4))
2) Slide the window
scala> xs.sliding(2)
res1: Iterator[List[Int]] = non-empty iterator
list.tail.head
gives the next element if you want to go through all the elements from the front of the list. This is because the head is the front-most element and tail is the rest of the list.
scala> val li = List (3, 4, 5)
li: List[Int] = List(3, 4, 5)
scala> li.tail.head
res74: Int = 4
If you don't want to compare just a single element, but a sequence of arbitrary length, you can do it in recursive function:
def compAdjectent (l: List [Int]) : Boolean = l match {
case Nil => false
case x :: Nil => false
case x :: y :: xs => if (x.equals (y)) true else compAdjectent (y :: xs)
}

What is an idiomatic Scala way to "remove" one element from an immutable List?

I have a List, which may contain elements that will compare as equal. I would like a similar List, but with one element removed. So from (A, B, C, B, D) I would like to be able to "remove" just one B to get e.g. (A, C, B, D). The order of the elements in the result does not matter.
I have working code, written in a Lisp-inspired way in Scala. Is there a more idiomatic way
to do this?
The context is a card game where two decks of standard cards are in play, so there may
be duplicate cards but still played one at a time.
def removeOne(c: Card, left: List[Card], right: List[Card]): List[Card] = {
if (Nil == right) {
return left
}
if (c == right.head) {
return left ::: right.tail
}
return removeOne(c, right.head :: left, right.tail)
}
def removeCard(c: Card, cards: List[Card]): List[Card] = {
return removeOne(c, Nil, cards)
}
I haven't seen this possibility in the answers above, so:
scala> def remove(num: Int, list: List[Int]) = list diff List(num)
remove: (num: Int,list: List[Int])List[Int]
scala> remove(2,List(1,2,3,4,5))
res2: List[Int] = List(1, 3, 4, 5)
Edit:
scala> remove(2,List(2,2,2))
res0: List[Int] = List(2, 2)
Like a charm :-).
You could use the filterNot method.
val data = "test"
list = List("this", "is", "a", "test")
list.filterNot(elm => elm == data)
You could try this:
scala> val (left,right) = List(1,2,3,2,4).span(_ != 2)
left: List[Int] = List(1)
right: List[Int] = List(2, 3, 2, 4)
scala> left ::: right.tail
res7: List[Int] = List(1, 3, 2, 4)
And as method:
def removeInt(i: Int, li: List[Int]) = {
val (left, right) = li.span(_ != i)
left ::: right.drop(1)
}
Unfortunately, the collections hierarchy got itself into a bit of a mess with - on List. For ArrayBuffer it works just like you might hope:
scala> collection.mutable.ArrayBuffer(1,2,3,2,4) - 2
res0: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 3, 2, 4)
but, sadly, List ended up with a filterNot-style implementation and thus does the "wrong thing" and throws a deprecation warning at you (sensible enough, since it is actually filterNoting):
scala> List(1,2,3,2,4) - 2
warning: there were deprecation warnings; re-run with -deprecation for details
res1: List[Int] = List(1, 3, 4)
So arguably the easiest thing to do is convert List into a collection that does this right, and then convert back again:
import collection.mutable.ArrayBuffer._
scala> ((ArrayBuffer() ++ List(1,2,3,2,4)) - 2).toList
res2: List[Int] = List(1, 3, 2, 4)
Alternatively, you could keep the logic of the code you've got but make the style more idiomatic:
def removeInt(i: Int, li: List[Int]) = {
def removeOne(i: Int, left: List[Int], right: List[Int]): List[Int] = right match {
case r :: rest =>
if (r == i) left.reverse ::: rest
else removeOne(i, r :: left, rest)
case Nil => left.reverse
}
removeOne(i, Nil, li)
}
scala> removeInt(2, List(1,2,3,2,4))
res3: List[Int] = List(1, 3, 2, 4)
def removeAtIdx[T](idx: Int, listToRemoveFrom: List[T]): List[T] = {
assert(listToRemoveFrom.length > idx && idx >= 0)
val (left, _ :: right) = listToRemoveFrom.splitAt(idx)
left ++ right
}
How about
def removeCard(c: Card, cards: List[Card]) = {
val (head, tail) = cards span {c!=}
head :::
(tail match {
case x :: xs => xs
case Nil => Nil
})
}
If you see return, there's something wrong.
// throws a MatchError exception if i isn't found in li
def remove[A](i:A, li:List[A]) = {
val (head,_::tail) = li.span(i != _)
head ::: tail
}
As one possible solutions you can find index of the first suitable element and then remove element at this index:
def removeOne(l: List[Card], c: Card) = l indexOf c match {
case -1 => l
case n => (l take n) ++ (l drop (n + 1))
}
Just another thought on how to do this using a fold:
def remove[A](item : A, lst : List[A]) : List[A] = {
lst.:\[List[A]](Nil)((lst, lstItem) =>
if (lstItem == item) lst else lstItem::lst )
}
Generic Tail Recursion Solution:
def removeElement[T](list: List[T], ele: T): List[T] = {
#tailrec
def removeElementHelper(list: List[T],
accumList: List[T] = List[T]()): List[T] = {
if (list.length == 1) {
if (list.head == ele) accumList.reverse
else accumList.reverse ::: list
} else {
list match {
case head :: tail if (head != ele) =>
removeElementHelper(tail, head :: accumList)
case head :: tail if (head == ele) => (accumList.reverse ::: tail)
case _ => accumList
}
}
}
removeElementHelper(list)
}
val list : Array[Int] = Array(6, 5, 3, 1, 8, 7, 2)
val test2 = list.splitAt(list.length / 2)._2
val res = test2.patch(1, Nil, 1)
object HelloWorld {
def main(args: Array[String]) {
var months: List[String] = List("December","November","October","September","August", "July","June","May","April","March","February","January")
println("Deleting the reverse list one by one")
var i = 0
while (i < (months.length)){
println("Deleting "+months.apply(i))
months = (months.drop(1))
}
println(months)
}
}