Scala - convert List of Lists into a single List: List[List[A]] to List[A] - scala

What's the best way to convert a List of Lists in scala (2.9)?
I have a list:
List[List[A]]
which I want to convert into
List[A]
How can that be achieved recursively? Or is there any other better way?

List has the flatten method. Why not use it?
List(List(1,2), List(3,4)).flatten
> List(1,2,3,4)

.flatten is obviously the easiest way, but for completeness you should also know about flatMap
val l = List(List(1, 2), List(3, 4))
println(l.flatMap(identity))
and the for-comprehension equivalent
println(for (list <- l; x <- list) yield x)
flatten is obviously a special case of flatMap, which can do so much more.

Given the above example, I'm not sure you need recursion. Looks like you want List.flatten instead.
e.g.
scala> List(1,2,3)
res0: List[Int] = List(1, 2, 3)
scala> List(4,5,6)
res1: List[Int] = List(4, 5, 6)
scala> List(res0,res1)
res2: List[List[Int]] = List(List(1, 2, 3), List(4, 5, 6))
scala> res2.flatten
res3: List[Int] = List(1, 2, 3, 4, 5, 6)

If your structure can be further nested, like:
List(List(1, 2, 3, 4, List(5, 6, List(7, 8))))
This function should give you the desire result:
def f[U](l: List[U]): List[U] = l match {
case Nil => Nil
case (x: List[U]) :: tail => f(x) ::: f(tail)
case x :: tail => x :: f(tail)
}

You don't need recursion but you can use it if you want:
def flatten[A](list: List[List[A]]):List[A] =
if (list.length==0) List[A]()
else list.head ++ flatten(list.tail)
This works like flatten method build into List. Example:
scala> flatten(List(List(1,2), List(3,4)))
res0: List[Int] = List(1, 2, 3, 4)

If you want to use flatmap, here is the the way
Suppose that you have a List of List[Int] named ll, and you want to flat it to List,
many people already gives you the answers, such as flatten, that's the easy way. I assume that you are asking for using flatmap method. If it is the case, here is the way
ll.flatMap(_.map(o=>o))

Related

List type mismatch when appending in Scala

Let's say I have following code:
val xs: List[Int] = List(1, 2, 3)
val ys: List[Int] = List(4, 5, 6)
val zs: List[Int] = xs.appended(ys)
The last line does not compile with an error:
Error:(162, 33) type mismatch; found : List[Int] required: Int val
zs: List[Int] = xs.appended(ys)
If I remove the explicit type declaration, then the code compiles, but the real problem is that
the error message appears in a recursive function where I would like to pass appended list as a parameter of type List[Int], so removing the explicit type is not an option.
According to scaladoc appended method takes only one argument, not an entire list. So the following examples will compile:
xs.appended(ys(0))
for(x <- xs) yield ys appended x
or appendAll:
xs appendAll ys
ys :++ xs
P.S.: Note, that appending to the list is not optimal, as it's time is proportional to the size of the list, prefer prepend instead:
ys ::: xs
According scala documentation appended method accepting just one element, not collection. And zs type after removing explicit types will be List[Any]:
val xs = List(1, 2, 3)
val ys = List(4, 5, 6)
val zs: List[Any] = xs.appended(ys) // List(1, 2, 3, List(4, 5, 6))
it compiles, but result will be List(1, 2, 3, List(4, 5, 6))
You can use method appendedAll to do that you want or just concatenate lists using concat or ++ operator :
val xs = List(1, 2, 3)
val ys = List(4, 5, 6)
val zs: List[Int] = xs ++ ys // List(1, 2, 3, 4, 5, 6)
val as: List[Int] = xs.appendedAll(ys) // List(1, 2, 3, 4, 5, 6)
val bs: List[Int] = xs.concat(ys) // List(1, 2, 3, 4, 5, 6)
1. val xs: List[Int] = List(1, 2, 3)
2. val ys: List[Int] = List(4, 5, 6)
3. val zs: List[Int] = xs.appended(ys)
The third line is a problem until you have the type declaration. Because when you compile your code compiler is not going to infer the type of the variable zs and it will expect the output of xs.appended(ys) to be a List[Int] which is not the case because xs is List[Int] now if you want to add an element in this list you can do xs.append(1) or any other integer but you are trying to insert List[Int] which is not Int.
Now when you remove the type declaration from line 3 it compile successfully because now compiler will infer the type of the variable zs and if you will see on REPL it will say the of this variable zs is List[Any].
Now if you want to add list into a list and get a flatten result you can simply use
val zs: List[Int] = xs ::: ys
If you will see the scala docs here
this is the signature of appended:
final def:+[B >: A](elem: B): List[B]
:+ is Alias for appended
:++ is Alias for appendedAll
As we can see from the signature appended function takes a parameter of type B and return List[B] in your case B is Int and you are trying to add List[Int].
I hope it clears why you are getting the compilation error.

Calling lists concatenation in Scala

Can someone explain what is going on with
scala> List(1,2).:::(List(3,4))
res15: List[Int] = List(3, 4, 1, 2)
scala> List(1,2) ::: List(3,4)
res16: List[Int] = List(1, 2, 3, 4)
How can the method call results differ while they should be the same method call?
In case of List(1,2).:::(List(3,4)) you call ::: method directly on object List(1,2). According to the docs:
#param prefix The list elements to prepend.
So you get: res15: List[Int] = List(3, 4, 1, 2)
When you do not use . (dot) notation ::: behaves as right associative operation according to the docs:
#usecase def :::(prefix: List[A]): List[A]
#inheritdoc
Example:
{{{List(1, 2) ::: List(3, 4) = List(3, 4).:::(List(1, 2)) = List(1, 2, 3, 4)}}}
That means that in the case of List(1,2) ::: List(3,4) method ::: is being called on object List(3,4).
Right associative operation means basically the following:
xs ::: ys ::: zs is interpreted as xs ::: (ys ::: zs)
Section 16.6 describes the same as example.

Scala Iteratively build lists

As a Scala beginner I am still struggling working with immutable lists. All I am trying to do append elements to my list. Here's an example of what I am trying to do.
val list = Seq()::Nil
val listOfInts = List(1,2,3)
listOfInts.foreach {case x=>
list::List(x)
}
expecting that I would end up with a list of lists: List(List(1),List(2),List(3))
Coming from java I am used to just using list.add(new ArrayList(i)) to get the same result. Am I way off here?
Since the List is immutable you can not modify the List in place.
To construct a List of 1 item Lists from a List, you can map over the List. The difference between forEach and map is that forEach returns nothing, i.e. Unit, while map returns a List from the returns of some function.
scala> def makeSingleList(j:Int):List[Int] = List(j)
makeSingleList: (j: Int)List[Int]
scala> listOfInts.map(makeSingleList)
res1: List[List[Int]] = List(List(1), List(2), List(3))
Below is copy and pasted from the Scala REPL with added print statement to see what is happening:
scala> val list = Seq()::Nil
list: List[Seq[Nothing]] = List(List())
scala> val listOfInts = List(1,2,3)
listOfInts: List[Int] = List(1, 2, 3)
scala> listOfInts.foreach { case x=>
| println(list::List(x))
| }
List(List(List()), 1)
List(List(List()), 2)
List(List(List()), 3)
During the first iteration of the foreach loop, you are actually taking the first element of listOfInts (which is 1), putting that in a new list (which is List(1)), and then adding the new element list (which is List(List()) ) to the beginning of List(1). This is why it prints out List(List(List()), 1).
Since your list and listOfInts are both immutable, you can't change them. All you can do is perform something on them, and then return a new list with the change. In your case list::List(x) inside the loop actually doesnt do anything you can see unless you print it out.
There are tutorials on the documentation page.
There is a blurb for ListBuffer, if you swing that way.
Otherwise,
scala> var xs = List.empty[List[Int]]
xs: List[List[Int]] = List()
scala> (1 to 10) foreach (i => xs = xs :+ List(i))
scala> xs
res9: List[List[Int]] = List(List(1), List(2), List(3), List(4), List(5), List(6), List(7), List(8), List(9), List(10))
You have a choice of using a mutable builder like ListBuffer or a local var and returning the collection you build.
In the functional world, you often build by prepending and then reverse:
scala> var xs = List.empty[List[Int]]
xs: List[List[Int]] = List()
scala> (1 to 10) foreach (i => xs = List(i) :: xs)
scala> xs.reverse
res11: List[List[Int]] = List(List(1), List(2), List(3), List(4), List(5), List(6), List(7), List(8), List(9), List(10))
Given val listOfInts = List(1,2,3), and you want the final result as List(List(1),List(2),List(3)).
Another nice trick I can think of is sliding(Groups elements in fixed size blocks by passing a "sliding window" over them)
scala> val listOfInts = List(1,2,3)
listOfInts: List[Int] = List(1, 2, 3)
scala> listOfInts.sliding(1)
res6: Iterator[List[Int]] = non-empty iterator
scala> listOfInts.sliding(1).toList
res7: List[List[Int]] = List(List(1), List(2), List(3))
// If pass 2 in sliding, it will be like
scala> listOfInts.sliding(2).toList
res8: List[List[Int]] = List(List(1, 2), List(2, 3))
For more about the sliding, you can have a read about sliding in scala.collection.IterableLike.
You can simply map over this list to create a List of Lists.
It maintains Immutability and functional approach.
scala> List(1,2,3).map(List(_))
res0: List[List[Int]] = List(List(1), List(2), List(3))
Or you, can also use Tail Recursion :
#annotation.tailrec
def f(l:List[Int],res:List[List[Int]]=Nil) :List[List[Int]] = {
if(l.isEmpty) res else f(l.tail,res :+ List(l.head))
}
scala> f(List(1,2,3))
res1: List[List[Int]] = List(List(1), List(2), List(3))
In scala you have two (three, as #som-snytt has shown) options -- opt for a mutable collection (like Buffer):
scala> val xs = collection.mutable.Buffer(1)
// xs: scala.collection.mutable.Buffer[Int] = ArrayBuffer(1)
scala> xs += 2
// res10: xs.type = ArrayBuffer(1, 2)
scala> xs += 3
// res11: xs.type = ArrayBuffer(1, 2, 3)
As you can see, it works just like you would work with lists in Java. The other option you have, and in fact it's highly encouraged, is to opt to processing list functionally, that's it, you take some function and apply it to each and every element of collection:
scala> val ys = List(1,2,3,4).map(x => x + 1)
// ys: List[Int] = List(2, 3, 4, 5)
scala> def isEven(x: Int) = x % 2 == 0
// isEven: (x: Int)Boolean
scala> val zs = List(1,2,3,4).map(x => x * 10).filter(isEven)
// zs: List[Int] = List(10, 20, 30, 40)
// input: List(1,2,3)
// expected output: List(List(1), List(2), List(3))
val myList: List[Int] = List(1,2,3)
val currentResult = List()
def buildIteratively(input: List[Int], currentOutput: List[List[Int]]): List[List[Int]] = input match {
case Nil => currentOutput
case x::xs => buildIteratively(xs, List(x) :: currentOutput)
}
val result = buildIteratively(myList, currentResult).reverse
You say in your question that the list is immutable, so you do are aware that you cannot mutate it ! All operations on Scala lists return a new list. By the way, even in Java using a foreach to populate a collection is considered a bad practice. The Scala idiom for your use-case is :
list ::: listOfInts
Shorter, clearer, more functional, more idiomatic and easier to reason about (mutability make things more "complicated" especially when writing lambda expressions because it breaks the semantic of a pure function). There is no good reason to give you a different answer.
If you want mutability, probably for performance purposes, use a mutable collection such as ArrayBuffer.

More efficient than acc.reverse ::: b?

I'm tail optimizing a recursive function. At the end, the result will be acc.reverse ::: b. This is O(n) because of reverse and :::. Is there a better performance way to combine the two lists? Thanks.
Ex. Combine List(3, 2, 1) and List(4, 5, 6) to List(1, 2, 3, 4, 5, 6)
The standard library includes the reverse_::: method for this:
scala> List(3, 2, 1) reverse_::: List(4, 5, 6)
res0: List[Int] = List(1, 2, 3, 4, 5, 6)
This is still O(n), but avoids the separate call to :::.
Just for the sake of fun and learning, you could easily implement this as a tail-recursive function:
#tailrec
def reverseConcat[A](lefts: List[A], rights: List[A]): List[A] =
lefts match {
case Nil => rights
case head::tail => reverseConcat(tail, head::rights)
}
Or using foldLeft:
def reverseConcat[A](lefts: List[A], rights: List[A]): List[A] =
lefts.foldLeft(rights)((xs, x) => x :: xs)
Note that reverse_::: is not implemented using tail-recursion; it uses a var behind the scenes, so might perform differently.

verifying a probability distribution with variable arguments sums to 1

I was wondering how you would write a method in Scala that takes a function f and a list of arguments args where each arg is a range. Suppose I have three arguments (Range(0,2), Range(0,10), and Range(1, 5)). Then I want to iterate over f with all the possibilities of those three arguments.
var sum = 0.0
for (a <- arg(0)) {
for (b <- arg(1)) {
for (c <- arg(2)) {
sum += f(a, b, c)
}
}
}
However, I want this method to work for functions with a variable number of arguments. Is this possible?
Edit: is there any way to do this when the function does not take a list, but rather takes a standard parameter list or is curried?
That's a really good question!
You want to run flatMap in sequence over a list of elements of arbitrary size. When you don't know how long your list is, you can process it with recursion, or equivalently, with a fold.
scala> def sequence[A](lss: List[List[A]]) = lss.foldRight(List(List[A]())) {
| (m, n) => for (x <- m; xs <- n) yield x :: xs
| }
scala> sequence(List(List(1, 2), List(4, 5), List(7)))
res2: List[List[Int]] = List(List(1, 4, 7), List(1, 5, 7), List(2, 4, 7), List(2
, 5, 7))
(If you can't figure out the code, don't worry, learn how to use Hoogle and steal it from Haskell)
You can do this with Scalaz (in general it starts with a F[G[X]] and returns a G[F[X]], given that the type constructors G and F have the Traverse and Applicative capabilities respectively.
scala> import scalaz._
import scalaz._
scala> import Scalaz._
import Scalaz._
scala> List(List(1, 2), List(4, 5), List(7)).sequence
res3: List[List[Int]] = List(List(1, 4, 7), List(1, 5, 7), List(2, 4, 7), List(2
, 5, 7))
scala> Seq(some(1), some(2)).sequence
res4: Option[Seq[Int]] = Some(List(1, 2))
scala> Seq(some(1), none[Int]).sequence
res5: Option[Seq[Int]] = None
That would more or less do the job (without applying f, which you can do separately)
def crossProduct[A](xxs: Seq[A]*) : Seq[Seq[A]]
= xxs.foldLeft(Vector(Vector[A]())){(res, xs) =>
for(r <- res; x <- xs) yield r :+ x
}
You can then just map your function on that. I'm not sure it's a very efficient implementation though.
That's the answer from recursive perspective. Unfortunately, not so short as others.
def foo(f: List[Int] => Int, args: Range*) = {
var sum = 0.0
def rec(ranges: List[Range], ints: List[Int]): Unit = {
if (ranges.length > 0)
for (i <- ranges.head)
rec(ranges.tail, i :: ints)
else
sum += f(ints)
}
rec(args.toList, List[Int]())
sum
}
Have a look at this answer. I use this code for exactly this purpose. It's slightly optimized. I think I could produce a faster version if you need one.