How to remove duplicate ints before a certain element in Scala - list

I have a list that can have certain numbers before an index that I don't need. For example:
val tempList: List[Any] = List(0,0,0,0,0,3,.,5,0,2,5)
How would I be able to remove all of the 0's before 3 without filtering out the 0 after the 3?

You can use dropWhile. Suppose you want to remove everything before 1:
scala> val l = List(0, 0, 0, 0, 1, 2, 0)
l: List[Int] = List(0, 0, 0, 0, 1, 2, 0)
scala> l.dropWhile(_ == 0)
res1: List[Int] = List(1, 2, 0)

What you need to do is a twist on dropWhile, that I would call filterWhile.
One simple solution that leverages the Collection API is the following:
def filterWhile[A](
list: List[A]
)(filterP: A => Boolean, whileP: A => Boolean): List[A] = {
val (toFilter, unfiltered) = list.span(whileP)
toFilter.filter(filterP) ++ unfiltered
}
You can play around with this code here on Scastie, alongside a couple of tests to verify it works as expected, which are the following:
def test[A](
input: List[A],
expected: List[A]
)(filterP: A => Boolean, whileP: A => Boolean): Unit =
assert(
filterWhile(input)(filterP, whileP) == expected,
s"input: $input, expected: $expected, got: ${filterWhile(input)(filterP, whileP)}"
)
test(
input = List(0, 0, 0, 0, 0, 3, '.', 5, 0, 2, 5),
expected = List(3, '.', 5, 0, 2, 5)
)(filterP = _ != 0, whileP = _ != 3)
test(
input = List(0, 0, 0, 1, 0, 3, '.', 5, 0, 2, 5),
expected = List(1, 3, '.', 5, 0, 2, 5)
)(filterP = _ != 0, whileP = _ != 3)
test(
input = List(1, 2, 3, 4),
expected = List(1, 2, 3, 4)
)(filterP = _ < 5, whileP = _ < 5)
In your case in particular all you have to do is invoke the function as follows:
filterWhile(tempList)(_ != 0, _ != 3)
Where the first predicate says how to filter and the second defines the "while" clause. I chose to align the predicate ordering to the name of the function (it first says "filter" and then "while") but feel free to adjust according to your preference. In any case, using named parameters is probably a good thing here.

Combining existing functions on lists, I came up with:
def filterUntil[A](list: List[A], filter: A => Boolean, cond: A => Boolean): List[A] = {
list.takeWhile(cond).filter(filter) ++ list.dropWhile(cond)
}
This produces much the same results as #stefanobaghino's answer.

This might be done with a foldLeft but in this case I would got for a recursive routine:
def remove(list: List[Any]): List[Any] = {
def loop(rem: List[Any], res: List[Any]): List[Any] =
rem match {
case Nil =>
res
case 0 :: tail =>
loop(tail, res)
case 3 :: _ =>
res ++ rem
case x :: tail =>
loop(tail, res :+ x)
}
loop(list, Nil)
}
remove(List(0,0,0,0,0,3,".",5,0,2,5))
// List(3, ., 5, 0, 2, 5)
Note that this won't be efficient for long lists because adding to the tail of a List gets very slow with longs lists.
Also, as noted in the comments, you should avoid Any if possible and use a more specific type.
[ Simplifications thanks to #MikhailIonkin ]

Related

Duplicate list elements which based on predicate

I would like to duplicate even/odd elements in a list.
def even(number: Int): Boolean = {
if(number%2 == 0) true
else false
}
I tried something weird cause i have no idea how should I do that exactly.
scala> var x = List(1, 2, 3)
x: List[Int] = List(1, 2, 3)
scala> x.map(el => if(even(el)) el::x)
res143: List[Any] = List((), List(2, 1, 2, 3), ())
This is not what I expected. I'd like to return only one list with all elements where odd/even are duplicated.
Thanks for your help.
You can use flatMap to return a list per element, either containing just the element itself if the predicate doesn't match, or a list with the element duplicated if it does:
def even(n : Int) : Boolean = n%2 == 0
val l = List(1,2,3)
l.flatMap(n => if(even(n)) List(n,n) else List(n)) // -> List(1, 2, 2, 3)
You can filter the first collection for even numbers, and than concat with the original list:
scala> var l = List(1,2,3)
l: List[Int] = List(1, 2, 3)
scala> l.filter(_ % 2 == 0) ++ l
res14: List[Int] = List(2, 1, 2, 3)
If you want the List[Int] sorted, you can apply that after the concatenation:
scala> l.filter(_ % 2 == 0) ++ l sorted
res15: List[Int] = List(1, 2, 2, 3)
This saves you the allocation of a new List[Int] for every match of even. You filter only the elements you need, creating one List[Int], and then concatenating it with the original.

How to implement 'takeUntil' of a list?

I want to find all items before and equal the first 7:
val list = List(1,4,5,2,3,5,5,7,8,9,2,7,4)
My solution is:
list.takeWhile(_ != 7) ::: List(7)
The result is:
List(1, 4, 5, 2, 3, 5, 5, 7)
Is there any other solution?
One-liner for impatient:
List(1, 2, 3, 7, 8, 9, 2, 7, 4).span(_ != 7) match {case (h, t) => h ::: t.take(1)}
More generic version:
It takes any predicate as argument. Uses span to do the main job:
implicit class TakeUntilListWrapper[T](list: List[T]) {
def takeUntil(predicate: T => Boolean):List[T] = {
list.span(predicate) match {
case (head, tail) => head ::: tail.take(1)
}
}
}
println(List(1,2,3,4,5,6,7,8,9).takeUntil(_ != 7))
//List(1, 2, 3, 4, 5, 6, 7)
println(List(1,2,3,4,5,6,7,8,7,9).takeUntil(_ != 7))
//List(1, 2, 3, 4, 5, 6, 7)
println(List(1,2,3,4,5,6,7,7,7,8,9).takeUntil(_ != 7))
//List(1, 2, 3, 4, 5, 6, 7)
println(List(1,2,3,4,5,6,8,9).takeUntil(_ != 7))
//List(1, 2, 3, 4, 5, 6, 8, 9)
Tail-recursive version.
Just to illustrate alternative approach, it's not any more efficient than previous solution.
implicit class TakeUntilListWrapper[T](list: List[T]) {
def takeUntil(predicate: T => Boolean): List[T] = {
def rec(tail:List[T], accum:List[T]):List[T] = tail match {
case Nil => accum.reverse
case h :: t => rec(if (predicate(h)) t else Nil, h :: accum)
}
rec(list, Nil)
}
}
Borrowing the takeWhile implementation from scala.collection.List and changing it a bit:
def takeUntil[A](l: List[A], p: A => Boolean): List[A] = {
val b = new scala.collection.mutable.ListBuffer[A]
var these = l
while (!these.isEmpty && p(these.head)) {
b += these.head
these = these.tail
}
if(!these.isEmpty && !p(these.head)) b += these.head
b.toList
}
Here's a way to get there with foldLeft, and a tail recursive version to short circuit long lists.
There's also the tests I used while playing around with this.
import scala.annotation.tailrec
import org.scalatest.WordSpec
import org.scalatest.Matchers
object TakeUntilInclusiveSpec {
implicit class TakeUntilInclusiveFoldLeft[T](val list: List[T]) extends AnyVal {
def takeUntilInclusive(p: T => Boolean): List[T] =
list.foldLeft( (false, List[T]()) )({
case ((false, acc), x) => (p(x), x :: acc)
case (res # (true, acc), _) => res
})._2.reverse
}
implicit class TakeUntilInclusiveTailRec[T](val list: List[T]) extends AnyVal {
def takeUntilInclusive(p: T => Boolean): List[T] = {
#tailrec
def loop(acc: List[T], subList: List[T]): List[T] = subList match {
case Nil => acc.reverse
case x :: xs if p(x) => (x :: acc).reverse
case x :: xs => loop(x :: acc, xs)
}
loop(List[T](), list)
}
}
}
class TakeUntilInclusiveSpec extends WordSpec with Matchers {
//import TakeUntilInclusiveSpec.TakeUntilInclusiveFoldLeft
import TakeUntilInclusiveSpec.TakeUntilInclusiveTailRec
val `return` = afterWord("return")
object lists {
val one = List(1)
val oneToTen = List(1, 2, 3, 4, 5, 7, 8, 9, 10)
val boat = List("boat")
val rowYourBoat = List("row", "your", "boat")
}
"TakeUntilInclusive" when afterWord("given") {
"an empty list" should `return` {
"an empty list" in {
List[Int]().takeUntilInclusive(_ == 7) shouldBe Nil
List[String]().takeUntilInclusive(_ == "") shouldBe Nil
}
}
"a list without the matching element" should `return` {
"an identical list" in {
lists.one.takeUntilInclusive(_ == 20) shouldBe lists.one
lists.oneToTen.takeUntilInclusive(_ == 20) shouldBe lists.oneToTen
lists.boat.takeUntilInclusive(_.startsWith("a")) shouldBe lists.boat
lists.rowYourBoat.takeUntilInclusive(_.startsWith("a")) shouldBe lists.rowYourBoat
}
}
"a list containing one instance of the matching element in the last index" should `return`
{
"an identical list" in {
lists.one.takeUntilInclusive(_ == 1) shouldBe lists.one
lists.oneToTen.takeUntilInclusive(_ == 10) shouldBe lists.oneToTen
lists.boat.takeUntilInclusive(_ == "boat") shouldBe lists.boat
lists.rowYourBoat.takeUntilInclusive(_ == "boat") shouldBe lists.rowYourBoat
}
}
"a list containing one instance of the matching element" should `return` {
"the elements of the original list, up to and including the match" in {
lists.one.takeUntilInclusive(_ == 1) shouldBe List(1)
lists.oneToTen.takeUntilInclusive(_ == 5) shouldBe List(1,2,3,4,5)
lists.boat.takeUntilInclusive(_ == "boat") shouldBe List("boat")
lists.rowYourBoat.takeUntilInclusive(_ == "your") shouldBe List("row", "your")
}
}
"a list containing multiple instances of the matching element" should `return` {
"the elements of the original list, up to and including only the first match" in {
lists.oneToTen.takeUntilInclusive(_ % 3 == 0) shouldBe List(1,2,3)
lists.rowYourBoat.takeUntilInclusive(_.length == 4) shouldBe List("row", "your")
}
}
}
}
Possible way of doing this:
def takeUntil[A](list:List[A])(predicate: A => Boolean):List[A] =
if(list.isEmpty) Nil
else if(predicate(list.head)) list.head::takeUntil(list.tail)(predicate)
else List(list.head)
You could use following function,
def takeUntil(list: List[Int]): List[Int] = list match {
case x :: xs if (x != 7) => x :: takeUntil(xs)
case x :: xs if (x == 7) => List(x)
case Nil => Nil
}
val list = List(1,4,5,2,3,5,5,7,8,9,2,7,4)
takeUntil(list) //List(1,4,5,2,3,5,5,7)
Tail Recursive version
def takeUntilRec(list: List[Int]): List[Int] = {
#annotation.tailrec
def trf(head: Int, tail: List[Int], res: List[Int]): List[Int] = head match {
case x if (x != 7 && tail != Nil) => trf(tail.head, tail.tail, x :: res)
case x => x :: res
}
trf(list.head, list.tail, Nil).reverse
}
Some ways by use built-in functions:
val list = List(1, 4, 5, 2, 3, 5, 5, 7, 8, 9, 2, 7, 4)
//> list : List[Int] = List(1, 4, 5, 2, 3, 5, 5, 7, 8, 9, 2, 7, 4)
//Using takeWhile with dropWhile
list.takeWhile(_ != 7) ++ list.dropWhile(_ != 7).take(1)
//> res0: List[Int] = List(1, 4, 5, 2, 3, 5, 5, 7)
//Using take with segmentLength
list.take(list.segmentLength(_ != 7, 0) + 1)
//> res1: List[Int] = List(1, 4, 5, 2, 3, 5, 5, 7)
//Using take with indexOf
list.take(list.indexOf(7) + 1)
//> res2: List[Int] = List(1, 4, 5, 2, 3, 5, 5, 7)
Many of the solutions here are not very efficient, because they explore the whole list, rather than stopping early. Here is a short solution using the in-built functions:
def takeUntil[T](c: Iterable[T], f: T => Boolean): Iterable[T] = {
val index = c.indexWhere(f)
if (index == -1) c else c.take(index + 1)
}

List of List in scala

I would like to know how can I create a List of List in the result of a reduce operation.
I've for example this lines
1,2,3,4
0,7,8,9
1,5,6,7
0,6,5,7
And I would like to get something like this
1, [[2,3,4],[5,6,7]]
0, [[7,8,9],[6,5,7]]
Thsi is my code
val parsedData = data.map { line =>
val parts = line.split(",")
val label = Integer.parseInt(parts(0))
(label, List(Integer.parseInt(parts(1)), Integer.parseInt(parts(2)), Integer.parseInt(parts(3)))
}
With this I get
1, [2,3,4]
0, [7,8,9]
1, [5,6,7]
0, [6,5,7]
But if I use a reduceByKey operation with a List.concat(_,_) I get one single List with all items concated.
parsedData.reduceByKey(List.concat(_,_))
I want a List of List, reduced by the Key.
Is there some other operation that i don't know?
Thanks a lot for your help!
Here is a working example:
val data = "1,2,3,4\n0,7,8,9\n1,5,6,7\n0,6,5,7".split("\n")
val parsedData = data.map{ line =>
val parts = line.split(",")
val label = Integer.parseInt(parts(0))
(label, List(Integer.parseInt(parts(1)), Integer.parseInt(parts(2)), Integer.parseInt(parts(3))))
}.toList
//parsedData: List[(Int, List[Int])] = List((1,List(2, 3, 4)), (0,List(7, 8, 9)), (1,List(5, 6, 7)), (0,List(6, 5, 7)))
parsedData.groupBy(_._1).mapValues(_.map(_._2))
// Map(1 -> List(List(2, 3, 4), List(5, 6, 7)), 0 -> List(List(7, 8, 9), List(6, 5, 7)))
I am not sure this is concat you are looking for.
Can you try with that:
parsedData.reduceByKey(_ :: _ :: Nil)
Which should literally create a new list with your elements inside

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

Keeping tracks of elements in a list in scala

Suppose you are given the following list: {1,0,0,3,4,0,8,0,5,6,0}. Is there any way I can assign a particular index to all the 0s in the list in SCALA? This index must then be used as a parameter to another function.
Not exactly sure what you mean, but perhaps this will give you some ideas:
scala> val list = List(3, 4, 0, 0, 3, 0, 2)
list: List[Int] = List(3, 4, 0, 0, 3, 0, 2)
scala> val indexed = list.zipWithIndex
indexed: List[(Int, Int)] = List((3,0), (4,1), (0,2), (0,3), (3,4), (0,5), (2,6))
scala> val zeroIndices = indexed collect { case (value, index) if value == 0 => index }
zeroIndices: List[Int] = List(2, 3, 5)
Bonus:
scala> zeroIndices map list
res1: List[Int] = List(0, 0, 0)