- scala> val nodupes = Map(1 -> "a", 2-> "b", 3 -> "c")
- nodupes: scala.collection.immutable.Map[Int,java.lang.String] = Map((1,a), (2,b), (3,c))
- // Scala 2.8+
- scala> nodupes map {_.swap}
- res4: scala.collection.immutable.Map[java.lang.String,Int] = Map((a,1), (b,2), (c,3))
- // Scala 2.7
- scala> Map() ++ (nodupes map {case (k,v) => (v,k)})
- res5: scala.collection.immutable.Map[java.lang.String,Int] = Map((a,1), (b,2), (c,3))
- // watch out if the values have duplicates you will loose information:
- scala> val dupes = Map(1 -> "a", 2-> "b", 3 -> "b")
- dupes: scala.collection.immutable.Map[Int,java.lang.String] = Map((1,a), (2,b), (3,b))
- scala> dupes map {_.swap}
- res6: scala.collection.immutable.Map[java.lang.String,Int] = Map((a,1), (b,3))
- // a way to not loose any data
- scala> dupes groupBy {_._2} map {case (key,value) => (key, value.unzip._1)}
- res12: scala.collection.Map[java.lang.String,scala.collection.immutable.Iterable[Int]] = Map((a,List(1)), (b,List(2, 3)))
- // I wanted to do the following for performance:
- scala> dupes.view groupBy {_._2} map {case (key,value) => (key, value.unzip._1)}
- java.lang.UnsupportedOperationException: IterableView((1,a), (2,b), (3,b)).newBuilder
- at scala.collection.TraversableViewLike$class.newBuilder(TraversableViewLike.scala:40)
- at scala.collection.IterableLike$$anon$1.newBuilder(IterableLike.scala:363)
- at scala.collection.TraversableLike$$anonfun$groupBy$1.apply(TraversableLike.scala:370)
- // but as you can see a view cannot yet be grouped. Perhaps in the future.
Showing posts with label Map. Show all posts
Showing posts with label Map. Show all posts
Wednesday, March 10, 2010
How to reverse a map
Suppose you wish to take a map and swap the keys with values. The stackoverflow question Elegant way to revers a map in scala offers some good suggestions
Labels:
groupby,
intermediate,
Map,
Scala,
swap
Monday, November 9, 2009
Using objects as functions
A fun but easily overlooked fact is that many classes inherit from a Function class and therefore can be used where "normal" functions can be used.
- scala> List(1,2) map (Map(1->"one",2->"two"))
- res0: List[java.lang.String] = List(one, two)
- scala> List(3,3,2) map (List('a', 'b', 'c','d'))
- res2: List[Char] = List(d, d, c)
Labels:
function,
intermediate,
list,
Map,
Scala
Friday, August 28, 2009
Apply-update methods
The apply and update methods have special meaning in Scala. They allow a developer to define semantics like java array access for an arbitrary class. For example:
As you can see you can invoke the apply method in a similar way that [] are used on arrays in Java. When you call '
Similarly '
This makes sense because if apply has many arguments representing the key then the same key must work for the update method for assignment. If you have many values to assign try:
- scala> class Phonebook {
- | val numbers = scala.collection.mutable.Map[String,String]()
- | def apply(name:String):String = numbers(name)
- | def update(name:String, number:String) = numbers(name) = number
- | }
- defined class Phonebook
- scala> val book = new Phonebook()
- book: Phonebook = Phonebook@1e406b09
- scala> book("jesse") = "123 456 7890"
- scala> println (book("jesse"))
- 123 456 7890
As you can see you can invoke the apply method in a similar way that [] are used on arrays in Java. When you call '
obj(param)
' the call is translated by the compiler to: 'obj.apply(param)
'. As such apply can have any number of arguments.Similarly '
obj(param) = value
' is compiled to 'obj.update(param,value)
'. Again the update method can have as many arguments as you wish. However only the last argument is treated as a value. So:- scala> class Echo {
- | def update(n:String, n2:String, n3:String ) = println(n,n2,n3)
- | }
- defined class Echo
- scala> val e = new Echo()
- e: Echo = Echo@2fa847df
- scala> e("hello", "hi") = "bonjour"
- (hello,hi,bonjour)
- scala> e("hello") = ("salut","bonjour")
:7: error: wrong number of arguments for method update: (String,String,String)Unit - e("hello") = ("salut","bonjour")
- ^
This makes sense because if apply has many arguments representing the key then the same key must work for the update method for assignment. If you have many values to assign try:
- scala> class Phonebook {
- | val numbers = scala.collection.mutable.Map[String, (Int, Int)]()
- | def apply(name:String) = numbers(name)
- | def update(name:String, number:(Int,Int)) = numbers(name) = number
- | }
- defined class Phonebook
- scala> val book2 = new Phonebook()
- book2: Phonebook = Phonebook@7a120cb3
- scala> book2("jesse") = (123, 4567890)
- scala> val (areaCode, local) = book2("jesse")
- areaCode: Int = 123
- local: Int = 4567890
Subscribe to:
Posts (Atom)