How to clone an iterator? - scala

Suppose I have an iterator:
val it = List("a","b","c").iterator
I want a copy of it; my code is:
val it2 = it.toList.iterator
It's correct, but seems not good. Is there any other API to do it?

The method you are looking for is duplicate.
scala> val it = List("a","b","c").iterator
it: Iterator[java.lang.String] = non-empty iterator
scala> val (it1,it2) = it.duplicate
it1: Iterator[java.lang.String] = non-empty iterator
it2: Iterator[java.lang.String] = non-empty iterator
scala> it1.length
res11: Int = 3
scala> it2.mkString
res12: String = abc

Warning: as of Scala 2.9.0, at least, this leaves the original iterator empty. You can val ls = it.toList; val it1 = ls.iterator; val it2 = ls.iterator to get two copies. Or use duplicate (which works for non-lists also).
Rex's answer is by the book, but in fact your original solution is by far the most efficient for scala.collection.immutable.List's.
List iterators can be duplicated using that mechanism with essentially no overhead. This can be confirmed by a quick review of the implementation of iterator() in scala.collection.immutable.LinearSeq, esp. the definition of the toList method, which simply returns the _.toList of the backing Seq which, if it's a List (as it is in your case) is the identity.
I wasn't aware of this property of List iterators before investigating your question, and I'm very grateful for the information ... amongst other things it means that many "list pebbling" algorithms can be implemented efficiently over Scala immutable Lists using Iterators as the pebbles.

Related

Is there a way to maintain ordering with Scala's breakOut?

I recently discovered breakOut and love how elegant it is, but noticed that it doesn't maintain order.
eg (from REPL):
scala> val list = List("apples", "bananas", "oranges")
list: List[String] = List(apples, bananas, oranges)
scala> val hs: HashMap[String, Int] = list.map{x => (x -> x.length)}(breakOut)
hs: scala.collection.mutable.HashMap[String,Int] = Map(bananas -> 7, oranges -> 7, apples -> 6)
I like using breakOut since it's really clean and neat but ordering does matter to me. Is there a way to get it to maintain order or do I have to add elements to my hashmap one at a time?
You see this behavior, because of the fact that HashMap is a data structure with undefined order. Even if you see some ordering of the elements in the hash map and it's consistent across the runs, you shouldn't depend on it. If you really need the order, consider using LinkedHashMap

dropWhile creates two iterators that have same underlying iterator?

I am observing, a behavior I don't fully understand:
scala> val a = Iterator(1,2,3,4,5)
a: Iterator[Int] = non-empty iterator
scala> val b = a.dropWhile(_ < 3)
b: Iterator[Int] = non-empty iterator
scala> b.next
res9: Int = 3
scala> b.next
res10: Int = 4
scala> a.next
res11: Int = 5
It looks like: iterator part (1,2,3) of iterator a is consumed, and (4,5) is left. Since 3 had to be evaluated it had to be consumed but by definition of dropWhile in has to be included in b. Iterator b is 3, (4,5) where (4,5) is whatever is left of a, the exactly same iterator. Is my understanding correct?
Given the above it looks quite dangerous, that behavior of b is altered by applying operations on a. Basically we have two objects pointing to the same location. Is using dropWhile like this bad style?
From the documentation for Iterator:
It is of particular importance to note that, unless stated otherwise, one should never use an iterator after calling a method on it. The two most important exceptions are also the sole abstract methods: next and hasNext.
Basically, once you called any method on an iterator, other than next and hasNext, you should consider it destroyed, and dispose of it.
Is using dropWhile like this bad style?
yes :-)

Scala ordered priority queue that always has the lowest number as the head, ascending order

I'd like to get a code sample that accomplishes ascending ordering of items in a priority queue.
I'd like to store Tuple2(Int, String) inside a priority queue so that it is ordered by the first element of the tuple in ascending order.
If my priority queue is called pq and I call pq.head I'd like to get the tuple with the lowest number, same thing with calling pq.dequeue.
scala> val pq = scala.collection.mutable.PriorityQueue[(Int, String)]()
pq: scala.collection.mutable.PriorityQueue[(Int, String)] = PriorityQueue()
scala> pq += Tuple2(8, "eight")
res60: pq.type = PriorityQueue((8,eight))
scala> pq += Tuple2(4, "four")
res61: pq.type = PriorityQueue((8,eight), (4,four))
scala> pq += Tuple2(7, "seven")
res62: pq.type = PriorityQueue((8,eight), (4,four), (7,seven))
How to apply ascending ordering by first element at time of insertion to the above?
Thanks
PriorityQueue.apply and PriorityQueue.empty both take an implicit Ordering instance that will be used to order the contents—the head will be the "largest" value according to that ordering. You're getting the default one for tuples, which is a lexicographic ordering on the elements of the tuple, which isn't what you want, since it'll make the tuple with the largest first element the head.
There are a couple of ways you can solve this issue. The easiest is just to call .reverse on your queue, which will give you a new queue with the same contents but the opposite ordering, which means the tuple with the lowest value will be the head.
You can also provide your own ordering when creating the queue:
import scala.collection.mutable.PriorityQueue
val pq = PriorityQueue.empty[(Int, String)](
implicitly[Ordering[(Int, String)]].reverse
)
Or if you explicitly don't want the second element to be consulted:
val pq = PriorityQueue.empty[(Int, String)](
Ordering.by((_: (Int, String))._1).reverse
)
This is possibly a little more efficient than reversing the queue, but probably not enough to worry about, so you should just choose the approach that you find most elegant.
If all you need is reversing the implicit ordering, you could just reverse the queue right away:
val pq = PriorityQueue.empty[(Int, String)].reverse
All you need to do is to mention ordering of the queue items. The following code will serve the purpose.
def ascendingOrder(tuple2: (Int, String)) = -tuple2._1
val pq = PriorityQueue[(Int, String)]()(Ordering.by(ascendingOrder))
pq += Tuple2(8, "eight")
pq += Tuple2(4, "four")
pq += Tuple2(7, "seven")
for (i <- 1 to 3) (println(pq.dequeue()))
Avoid using reverse as it will create unnecessary overheads.
From the scaladoc:
Only the dequeue and dequeueAll methods will return methods in priority order (while removing elements from the heap). Standard collection methods including drop and iterator will remove or traverse the heap in whichever order seems most convenient.
That caveat seems to also apply to .head, but .dequeue returns elements in order.
The default ordering is descending (since the highest priority comes out first), but you can explicitly pass a reversed order when constructing:
val normalOrder = implicitly[Ordering[(Int, String)]]
val reversedOrder = Ordering.reverse(normalOrder)
val pq = scala.collection.mutable.PriorityQueue[(Int, String)](reversedOrder)

Scala convert Option to an Int

I have looked at these links
http://blog.danielwellman.com/2008/03/using-scalas-op.html
http://blog.tmorris.net/scalaoption-cheat-sheet/
I have a map of [String, Integer] and when I do a map.get("X") I get an option. I would like the following.
val Int count = map.get(key);
// If the key is there I would like value if it is not I want 0
How do I achieve this in one line? I need to do this several times. It looks a bit inefficient to write a function everytime for doing this. I am sure there is some intelligent one line quirk that I am missing but I really like to get the value into an integer in ONE line :)
Just use getOrElse method:
val count: Int = map.getOrElse(key,0);
Note also, that in Scala you write type after name, not before.
#om-nom-nom (classic screen name) has the correct answer, but in the interest of providing yet another way™
val count = map.get(key) fold(0)(num => num)
Before in-the-know users bash me with, "Option has no fold!", fold has been added to Option in Scala 2.10
getOrElse is of course better in the current case, but in some Some/None scenarios it may be interesting to 1-liner with fold like so (edited complements of #Debiliski who tested against latest 2.10 snapshot):
val count = map.get(k).fold(0)(dao.userlog.count(_))
I suppose in 2.9.2 and under we can already do:
val count = map get(k) map ( dao.userlog.count(_) ) getOrElse(0)
Which is to say, in Scala there is often more than one way to do the same thing: in the linked thread, the OP shows more than 10 alternative means to achieve Option fold ;-)
Yet another way.
import scalaz._, Scalaz._
scala> val m = Map(9 -> 33)
m: scala.collection.immutable.Map[Int,Int] = Map(9 -> 33)
scala> m.get(9).orZero
res3: Int = 33
scala> m.get(8).orZero
res4: Int = 0

Why does method "combinations" return Iterator rather than Stream in Scala?

I noticed that method combinations (from here) returns Iterator. It looks reasonable that the method should be "lazy" to avoid generating all combinations in advance. Now I wonder, why it returns Iterator instead of Stream (which is a lazy list in Scala).
So, why does combinations return Iterator rather than Stream ?
With Stream it is more likely that all generated values will be held in memory.
scala> val s = Stream.iterate(0)(_ + 1)
s: scala.collection.immutable.Stream[Int] = Stream(0, ?)
scala> s.drop(3).head
res1: Int = 3
scala> s
res2: scala.collection.immutable.Stream[Int] = Stream(0, 1, 2, 3, ?)
When you retain a reference to your Stream, all generated elements will remain in memory. With an Iterator this is less likely to happen.
Of course this does not have to be the reason why the Scala library is designed the way it is...
I think because Stream caches all previously returned elements, so you would end up with all of them in memory. Iterator only returns the next one
As I can see on CombinationsItr code, you have a lazy evaluation each time you call next method.
See https://lampsvn.epfl.ch/trac/scala/browser/scala/tags/R_2_9_1_final/src//library/scala/collection/SeqLike.scala#L198
So when using next to get the next combination like this for example :
scala> val combinations = "azertyuiop".combinations(2)
scala> combinations.next
res9: String = az
the result of next is evaluated lazily.
Iterator is cheaper than Stream. You can always get the latter from the former, if you need.