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)
Related
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.
Since searching for :+ doesn't yield any results (thanks google!) I couldn't find any answer to my question:
Why is:
a :+ b
resulting in
List[Any]
if both 'a' and 'b' are of type
List[Int]
try it out yourself, following won't compile (Scala 2.11.6, Idea14):
object AAA extends App {
val a: List[Int] = List[Int]()
val b: List[Int] = List[Int]()
val x: List[Int] = a :+ b
}
thx in advance
:+ appends a single element to a List. So you are appending a List[Int] to a List[Int], resulting in something like (if a and b are both set to List(1, 2)):
List(1, 2, List(1, 2))
Scala calculates the most common type between the element type (Int) and the thing you append (List[Int]), which is Any.
You probably wanted to concatenate two lists:
val x: List[Int] = a ++ b
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()
Is there any way to efficiently do this, perhaps through toBuffer or to methods? My real problem is I'm building a List off a parser, as follows:
lazy val nodes: Parser[List[Node]] = phrase(( nodeA | nodeB | nodeC).*)
But after building it, I want it to be a buffer instead - I'm just not sure how to build a buffer straight from the parser.
to indeed does the trick, and it is pretty trivial to use:
scala> val l = List(1,2,3)
l: List[Int] = List(1, 2, 3)
scala> l.to[ListBuffer]
res1: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2, 3)
Works in scala 2.10.x
For scala 2.9.x, you can do:
scala> ListBuffer.empty ++= l
res1: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2, 3)
I have 4 elements:List[List[Object]] (Objects are different in each element) that I want to zip so that I can have a List[List[obj1],List[obj2],List[obj3],List[obj4]]
I tried to zip them and I obtained a nested list that I can't apply flatten to because it says: no implicit argument matching parameter type.
How can I solve this? should I try another way or is there any way to make the flatten work?
I'm kinda new to scala so it may be a dumb question :D
Thanks in advance!
clau
For One Nested List:
flatten will do:
scala> List(List(1), List(2), List(3)).flatten
res4: List[Int] = List(1, 2, 3)
scala> List(List(List(1)), List(List(2)), List(List(3))).flatten
res5: List[List[Int]] = List(List(1), List(2), List(3))
For multiple Nested Lists then you can:
def flatten(ls: List[Any]): List[Any] = ls flatMap {
case i: List[_] => flatten(i)
case e => List(e)
}
val k = List(1, List(2, 3), List(List(List(List(4)), List(5)), List(6, 7)), 8)
flatten(k)
It prints List[Any] = List(1, 2, 3, 4, 5, 6, 7, 8)
Before Scala 2.9
From the error you pasted, it looks like you're trying to call the flatten instance method of the nested list itself. That requires an implicit conversion to make something of type Iterable out of whatever types the List contains. In your case, it looks like the compiler can't find one.
Use flatten from the List singleton object, which doesn't require that implicit parameter:
scala> val foo = List(List(1), List("a"), List(2.3))
foo: List[List[Any]] = List(List(1), List(a), List(2.3))
scala> List.flatten(foo)
res1: List[Any] = List(1, a, 2.3)
After Scala 2.9
Just use foo.flatten.
The question is very vague. You should plain paste what you have, instead of trying to describe it. It would make everyone's (including your's) life much easier.
The code below is one example based on an assumption of what you have.
scala> List(List(1))
res0: List[List[Int]] = List(List(1))
scala> List(List(2))
res1: List[List[Int]] = List(List(2))
scala> List(List(3))
res2: List[List[Int]] = List(List(3))
scala> List(List(4))
res3: List[List[Int]] = List(List(4))
scala> res0 ::: res1 ::: res2 ::: res3
res4: List[List[Int]] = List(List(1), List(2), List(3), List(4))
In scala 2.10.2
scala> val foo = List(List(1), List("a"), List(2.3))
foo: List[List[Any]] = List(List(1), List(a), List(2.3))
scala> foo.flatten
res0: List[Any] = List(1, 2, a, 2.3)
working fine but
if you run like
scala> val foo = List(List(1,2), 2, List(2.3))
foo: List[Any] = List(List(1, 2), 2, List(2.3))
scala> foo.flatten
<console>:9: error: No implicit view available from Any => scala.collection.GenTraversableOnce[B].
foo.flatten
for that i write function
scala> def flat(ls: List[Any]): List[Any]= ls flatten {
| case t: List[Any] => flat(t)
| case c => List(c)
| }
flat: (ls: List[Any])List[Any]
scala> flat(List(List(1,2),2,List(2.3)))
res2: List[Any] = List(1, 2, 2, 2.3)
It helps if we have an example. Your code should look something like:
val f = List(1, 2)
val s = List(3, 4)
val top = List(f, s)
List.flatten(top) // returns List(1, 2, 3, 4)
You can only zip two lists at a time with list1 zip list2, and the type signature for the return values is List[(A,B)] not List[List[obj1],List[obj2],List[obj3],List[obj4]]
Consider List.concat, for instance
List.concat(List(1), List(2,22), List(3)) // delivers List(1, 2, 22, 3)