Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala - How to define map, where value depends on key?

Is there a way to define a Map, where Map value depends on its key, like

Map(key -> f(key), key2 -> f(key2), ...).
like image 610
Dmitry Meshkov Avatar asked Feb 18 '15 12:02

Dmitry Meshkov


2 Answers

You're looking at this the wrong way...

A Map[K,V] is also an instance of Partialfunction[K,V]. So change everywhere you're using your Map type (vals, method params, etc.) to be a PartialFunction.

Then you can just work with f directly, or supply a Map[K,V] as the instance wherever you don't have a simple algebraic relationship between keys and values.

e.g.

def methodUsingMapping(x: PartialFunction[Int,Boolean]) = ...

//then
val myMap = Map(1->true, 2->true, 3->false)
methodUsingMapping(myMap)


//or
val isEven = PartialFunction(n: Int => n % 2 == 0)
methodUsingMapping(isEven)

//or
//note: case statements in a block is the smart way
//      to define a partial function
//      In this version, the result isn't even defined for odd numbers
val isEven: PartialFunction[Int,Boolean] = {
  case n: Int if n % 2 == 0 => true
}
methodUsingMapping(isEven)

You also might also want to consider using (K) => Option[V], in which case you can supply an instance of the type via the lift method, which maps inherit from PartialFunction

e.g.

def methodUsingMapping(x: (Int)=>Option[Boolean]) = ...

//then
val myMap = Map(1->true, 2->true, 3->false)
methodUsingMapping(myMap.lift)

//or
def isEven(n: Int) = Some(n % 2 == 0)
methodUsingMapping(isEven)

//or
def isEven(n: Int) = n % 2 == 0
methodUsingMapping(x => Some(isEven(x)))
like image 122
Kevin Wright Avatar answered Sep 20 '22 23:09

Kevin Wright


Lets say you have your keys in a list like this, and you want to convert it map with squares as values.

scala> val keyList = ( 1 to 10 ).toList
keyList: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

scala> val doSquare = ( x: Int ) => x * x
doSquare: Int => Int = <function1>

// Convert it to the list of tuples - ( key, doSquare( key ) )
scala> val tupleList = keyList.map( key => ( key, doSquare( key ) ) )
tuple: List[(Int, Int)] = List((1,1), (2,4), (3,9), (4,16), (5,25), (6,36), (7,49), (8,64), (9,81), (10,100))

val keyMap = tuple.toMap
keyMap: scala.collection.immutable.Map[Int,Int] = Map(5 -> 25, 10 -> 100, 1 -> 1, 6 -> 36, 9 -> 81, 2 -> 4, 7 -> 49, 3 -> 9, 8 -> 64, 4 -> 16)

Or to do it in one line

( 1 to 10 ).toList.map( x => ( x, x * x ) ).toMap

Or... if you have just few keys... then you can write the specific code

Map( 1 -> doSquare( 1 ), 2 -> doSquare( 2 ) )
like image 32
sarveshseri Avatar answered Sep 18 '22 23:09

sarveshseri