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

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)

Related

takeWhile in Scala for element n+1

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)

Built-in method for rolling Scala List or Seq

I'm trying to roll a list, for example like so:
val notRolled = (1 to 5).toList // List(1,2,3,4,5)
val rolledBy1 = rollList(notRolled,1) // List(2,3,4,5,1)
val rolledBy2 = rollList(notRolled,2) // List(3,4,5,1,2)
val rolledBy3 = rollList(notRolled,3) // List(4,5,1,2,3)
val rolledBy4 = rollList(notRolled,4) // List(5,1,2,3,4)
val rolledBy5 = rollList(notRolled,5) // List(1,2,3,4,5)
val rolledByM1 = rollList(notRolled,-1) // List(5,1,2,3,4)
val rolledByM2 = rollList(notRolled,-2) // List(4,5,1,2,3)
val rolledByM3 = rollList(notRolled,-3) // List(3,4,5,1,2)
val rolledByM4 = rollList(notRolled,-4) // List(2,3,4,5,1)
val rolledByM5 = rollList(notRolled,-5) // List(1,2,3,4,5)
I had a look at scala-lang.org and can't seem to find anything that matches my requirement.
Is there a built-in method for rolling a list?
If not, is there a more efficient way to do it than this:
def rollList[T](theList: List[T], itemsToRoll: Int): List[T] = {
val split = {
if (itemsToRoll < 0) (theList.size + itemsToRoll % theList.size)
else itemsToRoll % theList.size
}
val (beginning, end) = theList.splitAt(split)
end ::: beginning
}
Using the enrich-my-library pattern will allow you to add the roll method directly to all the collections so that you can call myList.roll(2), as opposed to roll(myList, 1).
Using the generic CanBuildFrom pattern allows you to make roll return the best possible type on these collections (so that roll on a List will return a List, but roll on an Iterable will return an Iterable).
All together, here is one option that abides by these patterns:
import scala.collection.generic.CanBuildFrom
import scala.collection.TraversableLike
implicit class TraversableWithRoll[A, Repr <: Traversable[A]](val xs: TraversableLike[A, Repr]) extends AnyVal {
def roll[That](by: Int)(implicit bf: CanBuildFrom[Repr, A, That]): That = {
val builder = bf()
val size = xs.size
builder.sizeHint(xs)
val leftBy = if (size == 0) 0 else ((by % size) + size) % size
builder ++= xs.drop(leftBy)
builder ++= xs.take(leftBy)
builder.result
}
}
This allows you to do some of the following:
List(1, 2, 3, 4, 5).roll(2) //List(4,5,1,2,3)
Seq(3, 4, 5).roll(-1) //Seq(5, 3, 4)
Notice the benefits of the fluent syntax enabled by the enrich-my-library pattern, and the stronger types enabled by the use of the CanBuildFrom implicit .
def rotate[A] (list: List[A], by: Int) = {
if (list.isEmpty) list
else {
val shift = (by % list.size + list.size) % list.size
val (l, r) = list.splitAt(shift)
r ++ l
}
}
val list = List(1, 2, 3, 4, 5)
rotate(list, 1) // List(2, 3, 4, 5, 1)
rotate(list, 2) // List(3, 4, 5, 1, 2)
rotate(list, -1) // List(5, 1, 2, 3, 4)
rotate(list, -2) // List(4, 5, 1, 2, 3)
rotate(list, -9) // List(2, 3, 4, 5, 1)
Here is one way of simulating a circular list in a functional way. I made it so that a positive i will do a right shift and a negative a left shift. This is the reverse of what the question has, but I felt it's more natural.
def shift[T](c: List[T], i: Int) = {
if(c.isEmpty) c
else {
val (h,t) = if (i >= 0) c.splitAt(c.size - i%c.size)
else c.splitAt(- i%c.size)
t ++ h
}
}
Here are some examples in the REPL:
cala> shift(List(1,2,4), 1)
res: List[Int] = List(4, 1, 2)
scala> shift(List(1,2,4), 2)
res: List[Int] = List(2, 4, 1)
scala> shift(List(1,2,4), 3)
res: List[Int] = List(1, 2, 4)
scala> shift(List(1,2,4), 4)
res: List[Int] = List(4, 1, 2)
scala> shift(List(1,2,4), 5)
res: List[Int] = List(2, 4, 1)
scala> shift(List(1,2,4), 6)
res: List[Int] = List(1, 2, 4)
scala> shift(List(1,2,4), -1)
res60: List[Int] = List(2, 4, 1)
scala> shift(List(1,2,4), -2)
res: List[Int] = List(4, 1, 2)
scala> shift(List(1,2,4), -3)
res: List[Int] = List(1, 2, 4)
scala> shift(List(1,2,4), -4)
res: List[Int] = List(2, 4, 1)
scala> shift(List(1,2,4), -5)
res: List[Int] = List(4, 1, 2)
scala> shift(List(1,2,4), -6)
res: List[Int] = List(1, 2, 4)
This is my pure functional very simple proposition:
def circ[A]( L: List[A], times: Int ): List[A] = {
if ( times == 0 || L.size < 2 ) L
else circ(L.drop(1) :+ L.head , times-1)
}
val G = List("1a","2b","3c")
println( circ(G,1) ) //List(2b, 3c, 1a)
println( circ(G,2) ) //List(3c, 1a, 2b)
println( circ(G,3) ) //List(1a, 2b, 3c)
println( circ(G,4) ) //List(2b, 3c, 1a)
Added for times < 0 (rolling backwards):
def circ[A]( L: List[A], times: Int ): List[A] = {
if ( times == 0 || L.size < 2 ) L
else if ( times < 0 ) circ(L.reverse,-times).reverse
else circ(L.drop(1) :+ L.head , times-1)
}
Given:
val notRolled = (1 to 5).toList
Let's say we want rotate with shift = 3
val shift = 3
notRolled.zipWithIndex.groupBy(_._2 < shift).values.flatten.map(_._1)
For negative values we should add 5(lists size), so for shift = -3 we will calculate
val shift = -3
notRolled.zipWithIndex.groupBy(_._2 < 2).values.flatten.map(_._1)
I'm going to incorporate the ideas above, about CanBuildFrom, just as soon as I understand Scala better (!), but in the meantime, I had to do precisely this for the sake of writing a Burrows-Wheeler Transform algorithm. Here, with no take() or drop(), and no errors on empty collections (and, yes, side-effecting code):
def roll[A](xs: Traversable[A]): Iterator[Traversable[A]] = {
var front = xs
var back = collection.mutable.Buffer[A]()
Iterator.continually(front ++ back).takeWhile { _ =>
val done = front.isEmpty
if (!done) {
back :+= front.head
front = front.tail
}
!done
}
}

Method that add and remove an element from a List

i'm writing a method that take a list: List[(String, Int)] , x:(String, Int) and a n: Int parameters and return a List[(String, Int)]
The list parameter represents the input list, the x element represents the element to add to the list, the n represents the maximum dimension of the list.
The method has the following behavior:
First of all check if the list has n elements.
If list has
less than n elements, the method add the x elements to the list.
Otherwise if the list contain an elements less than x, the
method remove the minimum element from the list, and add the x
element to the list.
I've implemented the method as the following:
def method(list: List[(String, Int)], x: (String, Int), n: Int) = {
if(list.size < n)
list :+ x
else {
var index = -1
var min = 10000000//some big number
for(el <- 0 to list.size) {
if(list(el)._2 < x._2 && list(el)._2 < min) {
min = list(el)._2
index = el
}
}
if(index != -1) {
val newList = list.drop(index)
newList :+ x
}
else list
}
}
Exist a way to express this behavior in a more clean way??
First, a corrected version of what you posted (but it appears, not what you intended)
def method(list: List[(String, Int)], x: (String, Int), n: Int) = {
if(list.size < n)
list :+ x
else {
var index = -1
for(i <- 0 until list.size) {
val el = list(i)
if(el._2 < x._2)
index = i
}
if(index != -1) {
val (before, after) = list.splitAt(index)
val newList = before ++ after.tail
newList :+ x
}
else list
}
}
And some tests
val l1 = List(("one", 1))
val l2 = method(l1, ("three", 3), 2)
//> l2 : List[(String, Int)] = List((one,1), (three,3))
val l3 = method(l2, ("four", 4), 2)
//> l3 : List[(String, Int)] = List((one,1), (four,4))
val l4 = method(l2, ("zero", 0), 2)
//> l4 : List[(String, Int)] = List((one,1), (three,3))
Neater version (but still not meeting the spec as mentioned in a comment from the OP)
def method(list: List[(String, Int)], x: (String, Int), n: Int) = {
if (list.size < n)
list :+ x
else {
val (before, after) = list.span(_._2 >= x._2)
if (after.isEmpty)
list
else
before ++ after.tail :+ x
}
}
Another version that always removes the minimum, if that's less than x.
def method(list: List[(String, Int)], x: (String, Int), n: Int) = {
if (list.size < n)
list :+ x
else {
val smallest = list.minBy(_._2)
if (smallest._2 < x._2) {
val (before, after) = list.span(_ != smallest)
before ++ after.tail :+ x
} else
list
}
}
and its test results
val l1 = List(("one", 1))
val l2 = method(l1, ("three", 3), 2)
//> l2 : List[(String, Int)] = List((one,1), (three,3))
val l3 = method(l2, ("four", 4), 2)
//> l3 : List[(String, Int)] = List((three,3), (four,4))
val l4 = method(l2, ("zero", 0), 2)
//> l4 : List[(String, Int)] = List((one,1), (three,3))
but as I say in a comment, better to use a method that processes the whole sequence of Xs and returns the top N.
I would separate the ordering from the method itself:
def method[A: Ordering](list: List[A], x: A, n: Int) = ...
What do you want to do if the list contains more than one element less than x? If you're happy with replacing all of them, you could use map rather than your handwritten loop:
list map {
case a if Ordering.lt(a, x) => x
case a => a
}
If you only want to replace the smallest element of the list, maybe it's neater to use min?
val m = list.min
if(m < x) {
val (init, m :: tail) = list.splitAt(list.indexOf(m))
init ::: x :: tail
else list

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)
}
}