Duplicate list elements which based on predicate - list

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.

Related

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

separate two lists by difference in elements in them

If I have
val incomingIds : List[Int] = ....
val existingIds : List[Int] = //this makes db calls and find existing records (only interested in returning ids)
Now next I want to compare incomingIds with existingIds in a following way
say I have
val incomingIds : List[Int] = List(2,3,4,5)
val existingIds : List[Int] = List(1,2,3,6)
What above sample suggests is that my API should be able to find ids that are subject for deletion (ones that exist in incomingIds but not in existingIds). In this sample existingIds have 1,4,5 but they aren't there in incomingIds means 1,4,5 should go into
val idsForDeletion :List[Int]
and there will be another list call it
val idsForInsertion :List[Int].
so 6 should go into idsForInsertion list.
Is there a simple way to partition lists such a way?
You can filter the items from each list that aren't included in the other one using scala's filterNot function:
val idsForDeletion = existingIds.filterNot(incomingIds.toSet)
val idsForInsertion = incomingIds.filterNot(existingIds.toSet)
you can use diff
def diff(that: collection.Seq[A]): List[A]
It Computes the multiset difference between this list and another sequence.
scala> val incomingIds : List[Int] = List(2,3,4,5)
incomingIds: List[Int] = List(2, 3, 4, 5)
scala> val existingIds : List[Int] = List(1,2,3,6)
existingIds: List[Int] = List(1, 2, 3, 6)
scala> (incomingIds diff existingIds).toSet
res1: scala.collection.immutable.Set[Int] = Set(4, 5)
scala> (existingIds diff incomingIds).toSet
res2: scala.collection.immutable.Set[Int] = Set(1, 6)

Get first n elements from List

I have a List
val family=List("1","2","11","12","21","22","31","33","41","44","51","55")
i want to take its first n elements but the problem is that parents size is not fixed.
val familliar=List("1","2","11") //n=3
You can use take
scala> val list = List(1,2,3,4,5,6,7,8,9)
list: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
scala> list.take(3)
res0: List[Int] = List(1, 2, 3)
List(1,2,3).take(100) //List(1,2,3)
The signature of take will compare the argument with index, so the incremental index will never more than argument
The signature of take
override def take(n: Int): List[A] = {
val b = new ListBuffer[A]
var i = 0
var these = this
while (!these.isEmpty && i < n) {
i += 1
b += these.head
these = these.tail
}
if (these.isEmpty) this
else b.toList
}
Use take:
val familliar = family.take(3)

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)

Scala - select elements from ordered list

I am looking for a nice way to remove first N elements which are equal from the ordered list, e.g.
List(1,1,1,2,3,3)
should return
removeSame(list) -> (1,1,1)
Is there a nice way to do it, rather than remove the head of the list and then use takeWhile on the remainder, and finally using dropwhile? I can think of simple non-functional solution but I was wondering whether any functional one also exists
The functional way to avoid the duplication of takeWhile and dropWhile to get a prefix and remainder is using span, i.e.
scala> val list = List(1,1,1,2,3,3)
list: List[Int] = List(1, 1, 1, 2, 3, 3)
scala> val (prefix, rest) = list span (_ == list.head)
prefix: List[Int] = List(1, 1, 1)
rest: List[Int] = List(2, 3, 3)
Is this what you look for?
scala> val l = List(1,1,1,2,3,3)
l: List[Int] = List(1, 1, 1, 2, 3, 3)
scala> l.takeWhile(_ == l.head)
res6: List[Int] = List(1, 1, 1)
scala> val l = List()
l: List[Nothing] = List()
scala> l.takeWhile(_ == l.head)
res7: List[Nothing] = List()
Not the best way of doing it, but this also works:
def removeSame(l: List) = if( !l.isEmpty) l.groupBy( x => x)(l.head) else List()