In Scala, List is Immutable But - list

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.

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.

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)

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

Scala, repeat a finite list infinitely

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.