I wrote a small code to count number of words in a text:
val fileSource = Source.fromFile("alice29.txt")
val words: Array[String] = fileSource.mkString.split("\\W+").map(x => x.toLowerCase())
println("different words: " + words.length)
println(words.groupBy(identity).map(t => (t._1, t._2.length)))
val unordered : Seq[(String, Int)] = words.groupBy(identity).map(t => (t._1, t._2.length)).toSeq
I would like to reverse the order by using
reverse. But it seems reverse cannot be applied to the
ListMap. Why? How to do it properly?
The error message is as follows
error: value reverse is not a member of scala.collection.immutable.ListMap[String,Int]
When you tried
reverse, did you get an error message, unexpected behavior, or what? If it was an error message, please include the entire message.
@yarchik You can usually find answers to these questions in the Standard Library. (Any particular reason why you use
Looking at Scala Standard Library 2.13.8 - scala.collection.immutable.ListMap we see that
reverse is not available for
Entries are stored internally in reversed insertion order, which means the newest key is at the head of the list. As such, methods such as head and tail are O(n), while last and init are O(1). Other operations, such as inserting or removing entries, are also O(n), which makes this collection suitable only for a small number of elements.
So I can kind of understand why
reverse was not implemented.
ListMap seems to be intended for a very particular use case.
You can use
reverse on the
Seq you initially had.
ListMap first and foremost is a
Map, which doesn’t have a notion of element ordering, thus no
#reverse. It does give some guarantees regarding the order of elements in iterators based on insertion order, but this is just an artifact of internal in-memory organization and not reflected in the API (and I wouldn’t really want to rely on these guarantees for anything important).
You could apply [EDIT:
#reverse on the
unordered pair seq, but you could sort in the required ordering directly, omitting the additional reversal.
unordered.sorted(Ordering.by[(String, Int), Int](_._2).reverse)
- You should always close the
Source after use. (Consider using
- I’d try to move away from
Array asap, e.g. by applying
#toVector or similar after the
- You could replace
val unordered = words.groupMapReduce(identity)(_ => 1)(_ + _).toVector
@sangamon Very useful, I learn a lot from all the remarks.