Remove current element from LinkedList - scala

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.

Related

Performance of concat and append in Scala List vs ListBuffer

I want to understand the difference in performance in append and concat between List and ListBuffer
var myList = List(1, 2)
myList = myList ::: List(4, 5)
myList = myList :+ 6
var myMutableList = ListBuffer(1, 2)
myMutableList = myMutableList ++ ListBuffer(4, 5)
myMutableList += 6
My understanding is that
myList = myList ::: List(4, 5)
will allocate space for a new list and iterate through the original myList and list to be concatenated and append all element to the new list
myList = myList :+ 6
will allocate space for a new list and iterate through the original myList and append the original item and the new item to the new list
myMutableList = myMutableList ++ ListBuffer(4, 5)
will, if there is enough space just append to the old list, but if there is not enough space will do the same thing as myList = myList ::: List(4, 5)
same with
myMutableList += 6
so ListBuffer is more efficient in both non indexed append and concat?
Firstly I would like to address this (IMHO) totally misleading syntax
myNewList: List[Int] = myList ::: List(4, 5)
From the Scala Doc:
/**
* Adds the elements of a given list in front of this list.
* #param prefix The list elements to prepend.
* #tparam B Type of elements in the prefix (a subtype or equal type to A)
* #tparam A Type of elements in the suffix
* #return a list resulting from the concatenation of the given list prefix and this list.
*/
def:::[B >: A](prefix: List[B]): List[B]
To clarify this syntax, here is an example of what this would look like with postfix notation (as you have) as compared to normal infix notation (apply a function to an object)
// Postfix on left, equivalent to infix on right
List(1, 2) ::: List(3, 4) = List(3, 4).:::(List(1, 2)) = List(1, 2, 3, 4)
What you are really writing above is this:
myNewList: List[Int] = List(4, 5).:::(myList)
Semantically, append is what it appears to do, but with infix notation, we see the prefix is the argument to this function, not the suffix.
As to the performance of concat both list and listbuffer have the same signature:
final def concat[B >: A](suffix: IterableOnce[B]): List[B] // Or ListBuffer[B] for `ListBuffer`
Thus concat is likely implemented using the append operations of their respective types, for Lists, this is linear; For a ListBuffer, this is constant. For small lists/buffers, however, this difference is likely arbitrary.
myList ::: List(4, 5) will reverse myList and then will start prepending each element of the reversed myList into List(4, 5). Thus, this is sharing / reusing the previous List(4, 5)
Edit: well, what I said above is what would happen if the stdlib List was truly immutable, but it is actually mutable (just not visible outside of the stdlib). Thus, the stdlib exploits that to create a new :: with the head of myList and the tail as List(4, 5) and then it will start modifying that tail of that new list to constantly prepend the remaining elements of myList - Anyways, the end result is the same complexity and the fact that List(4, 5) is shared; just faster!
myList :+ 6 will indeed need to reallocate a new list from scratch and is very inefficient.
myMutableList ++ ListBuffer(4, 5) this is probably a bad idea since the idea of using a mutable collection is to mutate it, you probably want to do this instead:
val myMutableList = ListBuffer(1, 2)
myMutableList ++= ListBuffer(4, 5)
myMutableList += 6
In this case, both ++= and += are very efficient since they are just prepending to an internal List inside the ListBuffer

Zip two Arrays, always 3 elements of the first array then 2 elements of the second

I've manually built a method that takes 2 arrays and combines them to 1 like this:
a0,a1,a2,b0,b1,a3,a4,a5,b2,b3,a6,...
So I always take 3 elements of the first array, then 2 of the second one.
As I said, I built that function manually.
Now I guess I could make this a one-liner instead with the help of zip. The problem is, that zip alone is not enough as zip builds tuples like (a0, b0).
Of course I can flatMap this, but still not what I want:
val zippedArray: List[Float] = data1.zip(data2).toList.flatMap(t => List(t._1, t._2))
That way I'd get a List(a0, b0, a1, b1,...), still not what I want.
(I'd then use toArray for the list... it's more convenient to work with a List right now)
I thought about using take and drop but they return new data-structures instead of modifying the old one, so not really what I want.
As you can imagine, I'm not really into functional programming (yet). I do use it and I see huge benefits, but some things are so different to what I'm used to.
Consider grouping array a by 3, and array b by 2, namely
val a = Array(1,2,3,4,5,6)
val b = Array(11,22,33,44)
val g = (a.grouped(3) zip b.grouped(2)).toArray
Array((Array(1, 2, 3),Array(11, 22)), (Array(4, 5, 6),Array(33, 44)))
Then
g.flatMap { case (x,y) => x ++ y }
Array(1, 2, 3, 11, 22, 4, 5, 6, 33, 44)
Very similar answer to #elm but I wanted to show that you can use more lazy approach (iterator) to avoid creating temp structures:
scala> val a = List(1,2,3,4,5,6)
a: List[Int] = List(1, 2, 3, 4, 5, 6)
scala> val b = List(11,22,33,44)
b: List[Int] = List(11, 22, 33, 44)
scala> val groupped = a.sliding(3, 3) zip b.sliding(2, 2)
groupped: Iterator[(List[Int], List[Int])] = non-empty iterator
scala> val result = groupped.flatMap { case (a, b) => a ::: b }
result: Iterator[Int] = non-empty iterator
scala> result.toList
res0: List[Int] = List(1, 2, 3, 11, 22, 4, 5, 6, 33, 44)
Note that it stays an iterator all the way until we materialize it with toList

Copy constructor of BitSet (or other collections) in Scala

I need to create a new instance of BitSet class from another BitSet object (input).
I expected something like new BitSet(input), but none found. I could get the new instance with map() method as follows, but I don't think this is the best solution.
var r = input.map(_ + 0)(BitSet.canBuildFrom)
What's the copy constructor of BitSet? What's the general rule for copy constructor in Scala?
You can create another with the bitmask of the first:
var r = new BitSet(input.toBitMask)
I think, the general rule is to use immutable collections. They are, well, immutable, so you can pass them around freely without taking special care for copying them.
When you need mutable collections, however, copying collections becomes useful. I discovered that using standard to method works:
scala> mutable.Set(1, 2, 3)
res0: scala.collection.mutable.Set[Int] = Set(1, 2, 3)
scala> res0.to[mutable.Set]
res1: scala.collection.mutable.Set[Int] = Set(1, 2, 3)
scala> res0 eq res1
res2: Boolean = false
However, it won't work with BitSet because it is not a generic collection, and to needs type constructor as its generic parameter. For BitSet you can use the method suggested by Lee. BTW, it is intended exactly for scala.collection.mutable.BitSet, because scala.collection.immutable.BitSet does not contain such constructor (nor does it need it).
The "copy" method on collections is called clone (to be consistent with Java style).
scala> collection.mutable.BitSet(1,2,3)
res0: scala.collection.mutable.BitSet = BitSet(1, 2, 3)
scala> res0.clone
res1: scala.collection.mutable.BitSet = BitSet(1, 2, 3)
scala> res0 += 4
res2: res0.type = BitSet(1, 2, 3, 4)
scala> res1
res40: scala.collection.mutable.BitSet = BitSet(1, 2, 3)

What is the current element in a Scala DoubleLinkedList?

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

Scala: Can I rely on the order of items in a Set?

This was quite an unplesant surprise:
scala> Set(1, 2, 3, 4, 5)
res18: scala.collection.immutable.Set[Int] = Set(4, 5, 1, 2, 3)
scala> Set(1, 2, 3, 4, 5).toList
res25: List[Int] = List(5, 1, 2, 3, 4)
The example by itself suggest a "no" answer to my question. Then what about ListSet?
scala> import scala.collection.immutable.ListSet
scala> ListSet(1, 2, 3, 4, 5)
res21: scala.collection.immutable.ListSet[Int] = Set(1, 2, 3, 4, 5)
This one seems to work, but should I rely on this behavior?
What other data structure is suitable for an immutable collection of unique items, where the original order must be preserved?
By the way, I do know about distict method in List. The problem is, I want to enforce uniqueness of items (while preserving the order) at interface level, so using distinct would mess up my neat design..
EDIT
ListSet doesn't seem very reliable either:
scala> ListSet(1, 2, 3, 4, 5).toList
res28: List[Int] = List(5, 4, 3, 2, 1)
EDIT2
In my search for a perfect design I tried this:
scala> class MyList[A](list: List[A]) { val values = list.distinct }
scala> implicit def toMyList[A](l: List[A]) = new MyList(l)
scala> implicit def fromMyList[A](l: MyList[A]) = l.values
Which actually works:
scala> val l1: MyList[Int] = List(1, 2, 3)
scala> l1.values
res0: List[Int] = List(1, 2, 3)
scala> val l2: List[Int] = new MyList(List(1, 2, 3))
l2: List[Int] = List(1, 2, 3)
The problem, however, is that I do not want to expose MyList outside the library. Is there any way to have the implicit conversion when overriding? For example:
trait T { def l: MyList[_] }
object O extends T { val l: MyList[_] = List(1, 2, 3) }
scala> O.l mkString(" ") // Let's test the implicit conversion
res7: String = 1 2 3
I'd like to do it like this:
object O extends T { val l = List(1, 2, 3) } // Doesn't work
That depends on the Set you are using. If you do not know which Set implementation you have, then the answer is simply, no you cannot be sure. In practice I usually encounter the following three cases:
I need the items in the Set to be ordered. For this I use classes mixing in the SortedSet trait which when you use only the Standard Scala API is always a TreeSet. It guarantees the elements are ordered according to their compareTo method (see the Ordered trat). You get a (very) small performance penalty for the sorting as the runtime of inserts/retrievals is now logarithmic, not (almost) constant like with the HashSet (assuming a good hash function).
You need to preserve the order in which the items are inserted. Then you use the LinkedHashSet. Practically as fast as the normal HashSet, needs a little more storage space for the additional links between elements.
You do not care about order in the Set. So you use a HashSet. (That is the default when using the Set.apply method like in your first example)
All this applies to Java as well, Java has a TreeSet, LinkedHashSet and HashSet and the corresponding interfaces SortedSet, Comparable and plain Set.
It is my belief that you should never rely on the order in a set. In no language.
Apart from that, have a look at this question which talks about this in depth.
ListSet will always return elements in the reverse order of insertion because it is backed by a List, and the optimal way of adding elements to a List is by prepending them.
Immutable data structures are problematic if you want first in, first out (a queue). You can get O(logn) or amortized O(1). Given the apparent need to build the set and then produce an iterator out of it (ie, you'll first put all elements, then you'll remove all elements), I don't see any way to amortize it.
You can rely that a ListSet will always return elements in last in, first out order (a stack). If that suffices, then go for it.