Scala, repeat a finite list infinitely - list

I want to use Stream class in scala to repeat a given list infinitely.
For example the list (1,2,3,4,5) I want to create a stream that gives me (1,2,3,4,5,1,2,3,4,5,1,2,3....)
So that I can wrap the take operation. I know this can be implemented in other ways, but I wanna do it this way for some reason, just humor me :)
So the idea is that with this infinite cycle created from some list, I can use take operation, and when it reaches the end of the list it cycles.
How do I make a stream which simply repeats a given list?

Very similar to #Eastsun's, but a bit more intention revealing. Tested in Scala 2.8.
scala> val l = List(1, 2, 3)
l: List[Int] = List(1, 2, 3)
scala> Stream.continually(l.toStream).flatten.take(10).toList
res3: List[Int] = List(1, 2, 3, 1, 2, 3, 1, 2, 3, 1)
Alternatively, with Scalaz:
scala> import scalaz._
import scalaz._
scala> import Scalaz._
import Scalaz._
scala> val l = List(1, 2, 3)
l: List[Int] = List(1, 2, 3)
scala> l.toStream.repeat[Stream].join.take(10).toList
res7: List[Int] = List(1, 2, 3, 1, 2, 3, 1, 2, 3, 1)

An alternative method is concatenating the .toStream of the input with itself recursively. That is,
scala> def xs: Stream[Int] = List(1, 2, 3).toStream #::: xs
xs: Stream[Int]
scala> xs.take(10).toList
res1: List[Int] = List(1, 2, 3, 1, 2, 3, 1, 2, 3, 1)

There is a simple way with Stream#flatten in scala 2.8
Welcome to Scala version 2.8.0.r20542-b20100116020126 (Java HotSpot(TM) Client VM, Java 1.6.0_18).
Type in expressions to have them evaluated.
Type :help for more information.
scala> def cycle[T](seq: Seq[T]) = Stream.from(0).flatten(_ => seq)
cycle: [T](seq: Seq[T])scala.collection.immutable.Stream[T]
scala> cycle(1::2::3::Nil)
res0: scala.collection.immutable.Stream[Int] = Stream(1, ?)
scala> res0.take(10)
res1: scala.collection.immutable.Stream[Int] = Stream(1, ?)
scala> res0.take(10).toList
res2: List[Int] = List(1, 2, 3, 1, 2, 3, 1, 2, 3, 1)

Here's an implementation which doesn't assume that length is efficient:
def rep[A](seq: Seq[A]) = {
def inner(proj: Seq[A]): Stream[A] = {
if (proj.isEmpty)
inner(seq)
else
Stream.cons(proj.first, inner(proj drop 1))
}
if (seq.isEmpty)
Stream.empty
else
inner(seq)
}
This should run in constant time for any Seq (including List or even Stream) and only imposes a constant time overhead to populate each element. Also, it works even for infinite sequences. So, you can call rep on an infinite Stream and the resulting Stream will be equivalent to the input.

Stolen blatently from the excellent Scala by Example book, chapter 12, and with a few modifications:
def repeatedSeq(idx: Int, lst:Seq[Int]): Stream[Int] = Stream.cons(lst(idx), repeatedSeq((idx + 1)%lst.length, lst))
for(i <- repeatedSeq(1,List(1,1,2,3,5))) println(i)
This works for all Seq types (unless they can't be read from multiple times, of course). Might not be efficient if the .length call is slow. Tested in Scala 2.7.7.

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.

In Scala, List is Immutable But

I am a beginner to Scala language. In Scala, List is Immutable as per below code:
scala> var list = List(1,2,3,4,5) // List created named ‘ list ’
list: List[Int] = List(1, 2, 3, 4, 5)
scala> 25 :: list // Prepend with Cons( :: ) , But here new list created.
res2: List[Int] = List(25, 1, 2, 3, 4, 5)
scala> list // print ‘ list ’
res3: List[Int] = List(1, 2, 3, 4, 5)
But,
scala> list
res1: List[Int] = List(1, 2, 3, 4, 5)
scala> list :+= 12 // append list with :+=
scala> list
res2: List[Int] = List(1, 2, 3, 4, 5, 12)
In above example, same "list" is appended. Then how list is immutable? It's confusing me. Any one kindly explain to me?
http://daily-scala.blogspot.co.uk/2010/03/implicit-operator.html
:+= is not just appending, it's appending to a new list and reassigning the variable to point to the new list. It's equivalent to list = list + 12.
25 ++ list is making a new list, but not assigning it anywhere.

How to add an element to List while making sure that list contains latest n elements in scala

In Scala, what is the best way to add an element to a list while making sure that the list always contains latest n elements.
So if list is (1, 2, 3, 4, 5) and n = 5, then adding 6 should result in (2, 3, 4, 5, 6).
One possible way could be:
list = list ::: List(6)
list = list.takeRight(5)
Are there any better ways? Also, is there a better data-structure for maintaining such frequently changing collection?
It sounds like a fixed size Circular Buffer would satisfy your need. I think apache commons provides some implementation.
A solution in scala using List could be:
scala> def dropHeadAndAddToList[T](obj: T, list: List[T]):List[T] = {
list.drop(1) :+ obj
}
dropHeadAndAddToList: [T](obj: T, list: List[T])List[T]
scala> val a = List(1,2,3,4,5)
a: List[Int] = List(1, 2, 3, 4, 5)
scala> dropHeadAndAddToList(6, a)
res0: List[Int] = List(2, 3, 4, 5, 6)

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()

How to flatten a List of different types in Scala?

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)