val a=((((1,2),3),4),5)
val result=...
Need to convert this to List(1,2,3,4,5)
In scala without using recursive loop.
Personally, I would either do pattern matching (which in this case grows very long), or use some custom flattening function, the pattern matching thing looks something like this:
a match {
case ((((b, c), d), e), f) => List(b, c, d, e, f)
}
Pretty much boilerplate code. Now the other approach might not be as safe as this, but I prefer it over the first one, it's still safe though (for Tuple2[Product, T] like types).
# import scala.reflect.ClassTag
import scala.reflect.ClassTag
# def flatten[T : ClassTag](product: Tuple2[Product, T]): List[T] = {
product.productIterator.toList.flatMap {
case t: T => t :: Nil
case p: Tuple2[Product, T] => flatten(p)
}
}
defined function flatten
# // =>
# val a=((((1,2),3),4),5)
a: ((((Int, Int), Int), Int), Int) = ((((1, 2), 3), 4), 5)
# flatten(a)
res3: List[Int] = List(1, 2, 3, 4, 5)
# val b = (((3, (1,2)),4),5)
b: (((Int, (Int, Int)), Int), Int) = (((3, (1, 2)), 4), 5)
# // I think this one works because of type erasure, should not have worked normally :)
# flatten(b)
res9: List[Int] = List(3, 1, 2, 4, 5)
Another option would be to use shapeless.
Related
So i need to implement a function that takes two lists and a function. The function then uses the elements of the two lists and applies the function on the elements and saves them into a list by using map and/or fold and the functions from the list class.
Example:
• zipWith((x: Int, y: Int) => x + y, List(1, 2, 3), List(4, 5, 6))
→ List(5, 7, 9)
• zipWith((x:Int,y:Int) => x, List(1,2,3), List(4,5,6))
→ List(1, 2, 3)
I do not know how to use the passed function and apply it on the two lists. My idea was to zip the two lists and then apply the function on every element of the zipped list.
The elegant solution is using pattern matching:
def zipWith[A, B, C](f: (A, B) => C, l1: List[A], l2: List[B]): List[C] = {
l1.zip(l2).map { case (x1, x2) => f(x1, x2) }
}
To solve this without pattern matching, you'll just need to access the tuple's fields directly:
def zipWith[A, B, C](f: (A, B) => C, l1: List[A], l2: List[B]): List[C] = {
l1.zip(l2).map(tuple => f(tuple._1, tuple._2))
}
Since you asked for a solution without pattern matching, I suggest the following one:
def zipWith[A, B, C](a: List[A], b: List[B])(f: (A, B) => C): List[C] = {
a.zip(b).map { tuple =>
f(tuple._1, tuple._2)
}
}
By moving f to a separate arguments list, your invocations could be shortened significantly:
val a = List(1, 2, 3)
val b = List(4, 5, 6)
zipWith(a, b)(_ + _) // List(5, 7, 9)
zipWith(a, b)(_ * _) // List(4, 10, 18)
Suppose I have a list of numbers and list of functions:
val xs: List[Int] = List(1, 2, 3)
val fs: List[Int => Int] = List(f1, f2, f3)
Now I would like to use an Applicative to apply f1 to 1, f2 to 2, etc.
val ys: List[Int] = xs <*> fs // expect List(f1(1), f2(2), f3(3))
How can I do it with Scalaz ?
pure for zip lists repeats the value forever, so it's not possible to define a zippy applicative instance for Scala's List (or for anything like lists). Scalaz does provide a Zip tag for Stream and the appropriate zippy applicative instance, but as far as I know it's still pretty broken. For example, this won't work (but should):
import scalaz._, Scalaz._
val xs = Tags.Zip(Stream(1, 2, 3))
val fs = Tags.Zip(Stream[Int => Int](_ + 3, _ + 2, _ + 1))
xs <*> fs
You can use the applicative instance directly (as in the other answer), but it's nice to have the syntax, and it's not too hard to write a "real" (i.e. not tagged) wrapper. Here's the workaround I've used, for example:
case class ZipList[A](s: Stream[A])
import scalaz._, Scalaz._, Isomorphism._
implicit val zipListApplicative: Applicative[ZipList] =
new IsomorphismApplicative[ZipList, ({ type L[x] = Stream[x] ## Tags.Zip })#L] {
val iso =
new IsoFunctorTemplate[ZipList, ({ type L[x] = Stream[x] ## Tags.Zip })#L] {
def to[A](fa: ZipList[A]) = Tags.Zip(fa.s)
def from[A](ga: Stream[A] ## Tags.Zip) = ZipList(Tag.unwrap(ga))
}
val G = streamZipApplicative
}
And then:
scala> val xs = ZipList(Stream(1, 2, 3))
xs: ZipList[Int] = ZipList(Stream(1, ?))
scala> val fs = ZipList(Stream[Int => Int](_ + 10, _ + 11, _ + 12))
fs: ZipList[Int => Int] = ZipList(Stream(<function1>, ?))
scala> xs <*> fs
res0: ZipList[Int] = ZipList(Stream(11, ?))
scala> res0.s.toList
res1: List[Int] = List(11, 13, 15)
For what it's worth, it looks like this has been broken for at least a couple of years.
I see a solution with streamZipApplicative :
import scalaz.std.stream._
import scalaz.Tags
val xs: List[Int] = List(1, 2, 3)
val fs: List[Int => Int] = List(f1, f2, f3)
val zippedLists = streamZipApplicative.ap(Tags.Zip(xs.toStream)) (Tags.Zip(fs.toStream))
val result = Tag.unwrap(zippedLists).toList
Learning Scalaz spends a few paragraphs on this topic in their introduction to Applicatives. They quote LYAHFGG:
However, [(+3),(2)] <> [1,2] could also work in such a way that the first function in the left list gets applied to the first value in the right one, the second function gets applied to the second value, and so on. That would result in a list with two values, namely [4,4]. You could look at it as [1 + 3, 2 * 2].
But then adds:
This can be done in Scalaz, but not easily.
The "not easily" part uses streamZipApplicative like in #n1r3's answer:
scala> streamZipApplicative.ap(Tags.Zip(Stream(1, 2)))(Tags.Zip(Stream({(_: Int) + 3}, {(_: Int) * 2})))
res32: scala.collection.immutable.Stream[Int] with Object{type Tag = scalaz.Tags.Zip} = Stream(4, ?)
scala> res32.toList
res33: List[Int] = List(4, 4)
The "not easily" is the part that bothers me. I'd like to borrow from #Travis Brown fantastic answer. He is comparing the use of monads and applicatives (i.e. why use applicatives when you have a monad?):
Second (and relatedly), it's just a solid development practice to use the least powerful abstraction that will get the job done.
So, I would say that until a framework provides an applicative that works like your first use-case:
val ys: List[Int] = xs <*> fs
To use zip and map here instead:
xs.zip(fs).map(p=>p._2.apply(p._1))
To me, this code is much clearer and simpler than the alternatives in scalaz. This is the least powerful abstraction that gets the job done.
I have a list of lists with the following data
val list = List(List("a","b","c"),List("d","e","f"),List("a","a","a"))
I want to disicover how many different data do I have in each position of the sublists
1 -> List("a","d","a")
2 -> List("b","e","a")
3 -> List("c","f","a")
Is there a way to do that? It doesn't need to be indexed, but I need the amount of different values per sublist index, the result could also be
2 // different values a and d
3 // different values b, e and a
3 // different values c, f and a
As I noted in a comment on Jhonny Everson's (almost right but now deleted) answer, you can use transpose to get a list of the columns, and then distinct to remove duplicates:
scala> list.transpose.map(_.distinct.size)
res0: List[Int] = List(2, 3, 3)
This will throw an exception if all the lists don't have the same size, but that's probably what you want.
scala> list.transpose.map(_.toSet.size)
res0: List[Int] = List(2, 3, 3)
The output of list.transpose is List(List(a, d, a), List(b, e, a), List(c, f, a)) which gives you the structure you want then map each List to a Set to get the unique elements and count them.
If you want unique elements per position, then you can use zipWithIndex and reverse the outputs.
scala> list.transpose.map(_.distinct).zipWithIndex.map(t => t._2 -> t._1)
res1: List[(Int, List[String])] = List((0,List(a, d)), (1,List(b, e, a)), (2,List(c, f, a)))
Here is the code you wanted:
var lOfl = List(List.range(1,5), List(2,2,2,3), Nil)
//> lOfl : List[List[Int]] = List(List(1, 2, 3, 4), List(2, 2, 2, 3), List())
for {
l <- lOfl
} yield l.toSet.count(_ => true) //> res1: List[Int] = List(4, 2, 0)
A sample list of list of Int is created as lOfl; for loop iterates through each list of Int; toSet converts list to set eliminating duplicate elements. then count function does as the name says it all.
OR use the Scala's most used collection function (:P :P), map, like below,
lOfl.map(l => l.toSet.count(_ => true) ) //> res2: List[Int] = List(4, 2, 0)
How to split a List of elements into lists with at most N items?
ex: Given a list with 7 elements, create groups of 4, leaving the last group possibly with less elements.
split(List(1,2,3,4,5,6,"seven"),4)
=> List(List(1,2,3,4), List(5,6,"seven"))
I think you're looking for grouped. It returns an iterator, but you can convert the result to a list,
scala> List(1,2,3,4,5,6,"seven").grouped(4).toList
res0: List[List[Any]] = List(List(1, 2, 3, 4), List(5, 6, seven))
There is much easier way to do the task using sliding method.
It works this way:
val numbers = List(1, 2, 3, 4, 5, 6 ,7)
Lets say you want to break the list into smaller lists of size 3.
numbers.sliding(3, 3).toList
will give you
List(List(1, 2, 3), List(4, 5, 6), List(7))
Or if you want to make your own:
def split[A](xs: List[A], n: Int): List[List[A]] = {
if (xs.size <= n) xs :: Nil
else (xs take n) :: split(xs drop n, n)
}
Use:
scala> split(List(1,2,3,4,5,6,"seven"), 4)
res15: List[List[Any]] = List(List(1, 2, 3, 4), List(5, 6, seven))
edit: upon reviewing this 2 years later, I wouldn't recommend this implementation since size is O(n), and hence this method is O(n^2), which would explain why the built-in method becomes faster for large lists, as noted in comments below. You could implement efficiently as follows:
def split[A](xs: List[A], n: Int): List[List[A]] =
if (xs.isEmpty) Nil
else (xs take n) :: split(xs drop n, n)
or even (slightly) more efficiently using splitAt:
def split[A](xs: List[A], n: Int): List[List[A]] =
if (xs.isEmpty) Nil
else {
val (ys, zs) = xs.splitAt(n)
ys :: split(zs, n)
}
I am adding a tail recursive version of the split method since there was some discussion of tail-recursion versus recursion. I have used the tailrec annotation to force the compiler to complain in case the implementation is not indeed tail-recusive. Tail-recursion I believe turns into a loop under the hood and thus will not cause problems even for a large list as the stack will not grow indefinitely.
import scala.annotation.tailrec
object ListSplitter {
def split[A](xs: List[A], n: Int): List[List[A]] = {
#tailrec
def splitInner[A](res: List[List[A]], lst: List[A], n: Int) : List[List[A]] = {
if(lst.isEmpty) res
else {
val headList: List[A] = lst.take(n)
val tailList : List[A]= lst.drop(n)
splitInner(headList :: res, tailList, n)
}
}
splitInner(Nil, xs, n).reverse
}
}
object ListSplitterTest extends App {
val res = ListSplitter.split(List(1,2,3,4,5,6,7), 2)
println(res)
}
I think this is the implementation using splitAt instead of take/drop
def split [X] (n:Int, xs:List[X]) : List[List[X]] =
if (xs.size <= n) xs :: Nil
else (xs.splitAt(n)._1) :: split(n,xs.splitAt(n)._2)
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)