Scala: Creating a list of tuples from list elements sequentially - list

I am very new to Scala so this question may be very naive.
I have a list like this List[Int] = List(0, 3, 6, 12, 14, 15, 16, 17). I am trying to create a list like this [(0,3),(3,6),(6,12)..] and so on. So far this is what I have tried:
val l1= List(0, 3, 6, 12, 14, 15, 16, 17)
var l2=scala.collection.mutable.ListBuffer[(Int,Int)]()
l1.zipWithIndex.slice(0,l1.length-1).foreach(x=>{val newval=(x._1,l1(x._2+1)); l2+=newval})
Two questions here:
If I don't use val newval, i.e. try to do l1.zipWithIndex.slice(0,l1.length-1).foreach(x=>l2+=(x._1,l1(x._2+1))), the compiler says:
<console>:10: error: type mismatch;
found : Int
required: (Int, Int)
l1.zipWithIndex.slice(0,l1.length-1).foreach(x=>l2+=(x._1,l1(x._2+1))). Why is that?
What would a way to do it without the mutable listbuffer?

+= is a method on the ListBuffer l2 that accepts repeated parameters. That means when you do something like this:
scala> var l2 = scala.collection.mutable.ListBuffer[(Int, Int)]()
l2: scala.collection.mutable.ListBuffer[(Int, Int)] = ListBuffer()
scala> l2 += (1, 2)
<console>:9: error: type mismatch;
found : Int(1)
required: (Int, Int)
l2 += (1, 2)
.. The compiler thinks you are trying to add multiple Ints to the ListBuffer, when you are trying to add a tuple. You need an extra set of parentheses.
l1.zipWithIndex.slice(0,l1.length-1).foreach(x=> l2 += ((x._1,l1(x._2+1)) ))
You can use sliding, which will create a "sliding window" across the collection to return a list of lists of a specific group size, with a step size of one by default:
scala> List(0, 3, 6, 12, 14, 15, 16, 17).sliding(2)
.map { case List(a, b) => (a, b) }.toList
res10: List[(Int, Int)] = List((0,3), (3,6), (6,12), (12,14), (14,15), (15,16), (16,17))

besides the sliding, you could slide like following:
val l1= List(0, 3, 6, 12, 14, 15, 16, 17)
val l2 = l1.take(l1.size - 1).zip(l1.tail)
updated
l1.zip(l1.tail) works.

Related

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)

List of List in scala

I would like to know how can I create a List of List in the result of a reduce operation.
I've for example this lines
1,2,3,4
0,7,8,9
1,5,6,7
0,6,5,7
And I would like to get something like this
1, [[2,3,4],[5,6,7]]
0, [[7,8,9],[6,5,7]]
Thsi is my code
val parsedData = data.map { line =>
val parts = line.split(",")
val label = Integer.parseInt(parts(0))
(label, List(Integer.parseInt(parts(1)), Integer.parseInt(parts(2)), Integer.parseInt(parts(3)))
}
With this I get
1, [2,3,4]
0, [7,8,9]
1, [5,6,7]
0, [6,5,7]
But if I use a reduceByKey operation with a List.concat(_,_) I get one single List with all items concated.
parsedData.reduceByKey(List.concat(_,_))
I want a List of List, reduced by the Key.
Is there some other operation that i don't know?
Thanks a lot for your help!
Here is a working example:
val data = "1,2,3,4\n0,7,8,9\n1,5,6,7\n0,6,5,7".split("\n")
val parsedData = data.map{ line =>
val parts = line.split(",")
val label = Integer.parseInt(parts(0))
(label, List(Integer.parseInt(parts(1)), Integer.parseInt(parts(2)), Integer.parseInt(parts(3))))
}.toList
//parsedData: List[(Int, List[Int])] = List((1,List(2, 3, 4)), (0,List(7, 8, 9)), (1,List(5, 6, 7)), (0,List(6, 5, 7)))
parsedData.groupBy(_._1).mapValues(_.map(_._2))
// Map(1 -> List(List(2, 3, 4), List(5, 6, 7)), 0 -> List(List(7, 8, 9), List(6, 5, 7)))
I am not sure this is concat you are looking for.
Can you try with that:
parsedData.reduceByKey(_ :: _ :: Nil)
Which should literally create a new list with your elements inside

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)

What is a DList?

I tried googling for this but all I got were stories about minor celebrities. Given the lack of documentation, what is a DList?
It's a Difference List, along the lines of "Difference List as functions"
scala> val (l1, l2, l3) = (List(1, 2, 3), List(4, 5, 6), List(7, 8, 9))
l1: List[Int] = List(1, 2, 3)
l2: List[Int] = List(4, 5, 6)
l3: List[Int] = List(7, 8, 9)
Efficient prepending:
scala> l1 ::: l2 ::: l3
res8: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
Inefficient appending. This creates an intermediate list (l1 ++ l2), then ((l1 ++ l2) ++ l3)
scala> l1 ++ l2 ++ l3 // inefficient
res9: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
DList stores up the appends, and only needs to create one complete list, effectively invoking:
scala> List(l1, l2, l3) reduceRight ( _ ::: _)
res10: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
Difference lists are a list-like data structure that supports O(1) append operations.
Append, and other operations that modify a list are represented via function composition of the modification functions, rather than directly copying the list.
An example, from Haskell's dlist library:
-- Lists as functions
newtype DList a = DL { unDL :: [a] -> [a] }
-- The empty list
empty = DL id
-- The append case: composition, a la Hughes
append xs ys = DL (unDL xs . unDL ys)
-- Converting to a regular list, linear time.
toList = ($[]) . unDL
The technique goes back at least to Hughes 84, A novel representation of lists and its application to the function "reverse", R. John Hughes, 1984., where, he proposes representing lists as functions, and append as function composition, allowing e.g. reverse to run in linear time. From the paper:
It's a data type in the non-canonical scalaz package, useful for typed lists with constant-time access at both ends. (The trick is to google for "scala" AND "dlist".)
From the project page of scalaz:
DList, a data type for representing elements of the same type with constant time append/prepend operations.