What is the current element in a Scala DoubleLinkedList? - scala

I'm looking at using a DoubleLinkedList. It's remove() method says "Removes the current node from the double linked list." but there are no other references to current in the page.
What is the current node, how do I set it, and surely this can't be the only way of removing an item?

A DoubleLinkedList is at the same time the list itself and a list node, similar to the :: for a regular List. You can navigate from one cell to the next or to the previous one with next and prev, respectively, and get the value of a cell with elem.
scala> val list = collection.mutable.DoubleLinkedList(1,2,3,4,5)
list: scala.collection.mutable.DoubleLinkedList[Int] = DoubleLinkedList(1, 2, 3, 4, 5)
scala> list.next.next.remove() // list.next.next points on 3rd cell
scala> list
res0: scala.collection.mutable.DoubleLinkedList[Int] = DoubleLinkedList(1, 2, 4, 5)
Be careful if you remove the first cell, as you’ll need to reassign your var holding the list to the next cell:
scala> val list = collection.mutable.DoubleLinkedList(1,2,3,4,5)
list: scala.collection.mutable.DoubleLinkedList[Int] = DoubleLinkedList(1, 2, 3, 4, 5)
scala> list.remove() // remove first item
scala> list // this is now a 'dangling' cell, although it still points to the rest of the list
res6: scala.collection.mutable.DoubleLinkedList[Int] = DoubleLinkedList(1, 2, 3, 4, 5) // uh? didn't I remove the first cell?
scala> list.next.prev // we can check that it is not pointed back to by its next cell
res7: scala.collection.mutable.DoubleLinkedList[Int] = null

Related

How to remove duplicates from list without using in inbuilt libraries such as distinct, groupBy(identity), toSet.. Etc

I wanted to write a Scala program that takes command-line args as list input and provide the output list without duplicates.
I want to know the custom implementation of this without using any libraries.
Input : 4 3 7 2 8 4 2 7 3
Output :4 3 7 2 8
val x= List(4, 3, 7, 2, 8, 4, 2, 7, 3)
x.foldLeft(List[Int]())((l,v)=> if (l.contains(v)) l else v :: l)
if you can't use contains you can do another fold
x.foldLeft(List[Int]())((l,v)=> if (l.foldLeft(false)((contains,c)=>if (c==v ) contains | true else contains | false)) l else v :: l)
Here's a way you could do this using recursion. I've tried to lay it out in a way that's easiest to explain:
import scala.annotation.tailrec
#tailrec
def getIndividuals(in: List[Int], out: List[Int] = List.empty): List[Int] = {
if(in.isEmpty) out
else if(!out.contains(in.head)) getIndividuals(in.tail, out :+ in.head)
else getIndividuals(in.tail, out)
}
val list = List(1, 2, 3, 4, 5, 4, 3, 5, 6, 0, 7)
val list2 = List(1)
val list3 = List()
val list4 = List(3, 3, 3, 3)
getIndividuals(list) // List(1, 2, 3, 4, 5, 6, 0, 7)
getIndividuals(list2) // List(1)
getIndividuals(list3) // List()
getIndividuals(list4) // List(3)
This function takes two parameters, in and out, and iterates through every element in the in List until it's empty (by calling itself with the tail of in). Once in is empty, the function outputs the out List.
If the out List doesn't contain the value of in you are currently looking at, the function calls itself with the tail of in and with that value of in added on to the end of the out List.
If out does contain the value of in you are currently looking at, it just calls itself with the tail of in and the current out List.
Note: This is an alternative to the fold method that Arnon proposed. I personally would write a function like mine and then maybe refactor it into a fold function if necessary. I don't naturally think in a functional, fold-y way so laying it out like this helps me picture what's going on as I'm trying to work out the logic.

Scala get next index in the list from current item

Say for example I am mapping one list to the next, and in the map I want to do some calculation with the current item in the list with the next item in the list.
def someFunc(L: List[Integer]) : List[Integer] = {
L.collect {
case k if (k != L(L.length-1)) //do something with k and the next element
}
}
A simple example is I want to go through this List of Integers, and map each number onto the next number in the list divided by it.
E.g. (1,2,3) -> (2/1, 3/2) == (2, 1.5)
I had thought about doing this using indexOf but I don't think that is efficient having to search the whole list for the current element even though I am already traversing each element in the list anyway.
Use .sliding for this:
scala> val l = List(1, 2, 3)
l: List[Int] = List(1, 2, 3)
scala> l.sliding(2).toList
res0: List[List[Int]] = List(List(1, 2), List(2, 3))
scala> l.sliding(2).collect { case x::y::Nil if y != 0 => x / y.toDouble }.toList
res1: List[Double] = List(0.5, 0.6666666666666666)

How map function does sorting in scala

The following code snippet
val keys=List(3,2,1,0)
val unsorted=List(1, 2, 3, 4)
val sorted =keys map unsorted
does sorting based on the keys.
Normally, map method takes a lambda and apply it to every element in the source. Instead the above code takes a list and does a sorting based on the index.
What is happening in this particular situation?
List is a partial function that goes from its indices to its values. You could look at it like this:
scala> List(3,2,1,0) map (i => List(1,2,3,4)(i))
res0: List[Int] = List(4, 3, 2, 1)
to verify
scala> val f: Int => Int = List(1, 2, 3, 4)
f: Int => Int = List(1, 2, 3, 4)
It does not sorting them, map takes a function, lets see:
that statement translates to:
keys.map(unsorted.apply)
Scala's List.apply(n: Int) function return nth element of list, in this case map makes it:
unsorted(3), unsorted(2), unsorted(1), unsorted(4)
which is
4,3,2,1 which is sorted only by chance in this case.
Test this:
scala> val keys = List(3,0,1,2)
keys: List[Int] = List(3, 0, 1, 2)
scala> val unsorted = List(10,20,30,40)
unsorted: List[Int] = List(10, 20, 30, 40)
scala> keys map unsorted
res0: List[Int] = List(40, 10, 20, 30)
In keys map unsorted for each value in keys we call the apply method in list unsorted which yields the element at a key position.
Swap elements in keys and note the outcome, for instance note the last key,
val keys=List(2,1,0,3)
val sorted = keys map unsorted
sorted: List[Int] = List(3, 2, 1, 4)
The function .map has not specific relation with sorting.
Your snipet is a specific case that happens to sort. If desugaring, it does as follows.
/* keys */List(3,2,1,0).map { i: Int =>
unsorted.apply(i)
}
It applies unsorted.apply with each value of keys (used as indexes).
It's not sorting at all. It is normal situation: map method takes a lambda and apply it to every element in the source. Just change your sorted list and you'll see it.

How to concatenate lists that are values of map?

Given:
scala> var a = Map.empty[String, List[Int]]
a: scala.collection.immutable.Map[String,List[Int]] = Map()
scala> a += ("AAA" -> List[Int](1,3,4))
scala> a += ("BBB" -> List[Int](4,1,4))
scala> a
res0: scala.collection.immutable.Map[String,List[Int]] = Map(AAA -> List(1, 3, 4), BBB -> List(4, 1, 4))
How to concatenate the values to a single iterable collection (to be sorted)?
List(1, 3, 4, 4, 1, 4)
How should I end this code?
a.values.[???].sorted
You should end it with:
a.values.flatten
Result:
scala> Map("AAA" -> List(1, 3, 4), "BBB" -> List(4, 1, 4))
res50: scala.collection.immutable.Map[String,List[Int]] = Map(AAA -> List(1, 3, 4), BBB -> List(4, 1, 4))
scala> res50.values.flatten
res51: Iterable[Int] = List(1, 3, 4, 4, 1, 4)
Updated:
For your specific case it's:
(for(vs <- a.asScala.values; v <- vs.asScala) yield v.asInstanceOf[TargetType]).sorted
This will work
a.values.flatten
//> res0: Iterable[Int] = List(1, 3, 4, 4, 1, 4)
Consider
a.flatMap(_._2)
which flattens up the second element of each tuple (each value in the map).
Equivalent in this case is also
a.values.flatMap(identity)
My appreciation of all answers I have received. Finally good points led to really working code. Below is real code fragment and x here is org.apache.hadoop.hbase.client.Put which makes all the 'devil in the details'. I needed HBase Put to be converted into list of appropriate data cells (accessible from puts through org.apache.hadoop.hbase.Cell interface) but yet I need disclosure of the fact they are indeed implemented as KeyValue (org.apache.hadoop.hbase.KeyValue).
val a : Put ...
a.getFamilyCellMap.asScala
.flatMap(
_._2.asScala.flatMap(
x => List[KeyValue](x.asInstanceOf[KeyValue]) )
).toList.sorted
Why so complex?
Put is Java type to represent 'write' operation content and we can get its cells only through map of cells families elements of which are lists. Of course they all are Java.
I have only access to interface (Cell) but I need implementation (KeyValue) so downcast is required. I have guarantee nothing else is present.
The most funny thing after all of this I decided to drop standard Put and encapsulate data into different container (which is my custom class) on earlier stage and this made things much more simple.
So more generic answer for this case where a is java.util.Map[?] with values of java.util.List[?] and elements of list are of BaseType but you need `TargetType is probably:
a.asScala.flatMap(
_._2.asScala.flatMap(
x => List[TargetType](x.asInstanceOf[TargetType]) )
).toList.sorted

Remove current element from LinkedList

In Scala: There appears to be no remove() method for LinkedList, for some reason I can't understand. There is one for DoubleLinkedList though, but I don;t need a double linked list.
Also, how could I set the current element to the first? And how do I know when it has reached the end (is it null?)
There is no current element in LinkedList.
There are only 2 fields in LinkedList: elem (or head) for element and next (or tail) for LinkedList.
You can test if LinkedList is empty using isEmpty. Every LinkedList contains an empty LinkedList as it's deepest tail. See documentation for ASCII illustration.
You can delete Nth element (if any) like this:
var current = myLinkedList.drop(n-2)
current.next = current.next.next
Example:
scala> val myList = LinkedList(1,2,3,4,5)
myList: scala.collection.mutable.LinkedList[Int] = LinkedList(1, 2, 3, 4, 5)
scala> val current = myList.drop(1)
current: scala.collection.mutable.LinkedList[Int] = LinkedList(2, 3, 4, 5)
scala> current.next = current.next.next
current.next: scala.collection.mutable.LinkedList[Int] = LinkedList(4, 5)
scala> myList
res0: scala.collection.mutable.LinkedList[Int] = LinkedList(1, 2, 4, 5)
You can't delete first element this way, but you can just forget about it:
scala> var myList = LinkedList(1,2,3,4,5)
myList: scala.collection.mutable.LinkedList[Int] = LinkedList(1, 2, 3, 4, 5)
scala> myList = myList.next
myList: scala.collection.mutable.LinkedList[Int] = LinkedList(2, 3, 4, 5)
first of all, is there a particular reason why you need a LinkedList over the standard List in Scala?
As warned in the scaladoc, you could easily end up in NPEs with LinkedList, whereas a List won't have this issue unless you actually introduce null values.
a List tail method is usually all you need. Please consider this approach first, and only resort to a specialized class if absolutely necessary.