How to create a map out of two lists? - scala

I have two lists
val a = List(1,2,3)
val b = List(5,6,7)
I'd like to create a Map like:
val h = Map(1->5, 2->6, 3->7)
basically iterating thru both the lists and assigning key value pairs.
How to do it properly in Scala?

You can zip the lists together into a list of tuples, then call toMap:
(a zip b) toMap
Note that if one list is longer than the other, it will be truncated.
Example:
val a = List(1, 2, 3)
val b = List(5, 6, 7)
scala> (a zip b) toMap
res2: scala.collection.immutable.Map[Int,Int] = Map(1 -> 5, 2 -> 6, 3 -> 7)
With truncation:
val c = List("a", "b", "c", "d", "e")
scala> (a zip c) toMap
res3: scala.collection.immutable.Map[Int,String] = Map(1 -> a, 2 -> b, 3 -> c)
(c zip a) toMap
res4: scala.collection.immutable.Map[String,Int] = Map(a -> 1, b -> 2, c -> 3)

Related

Scala two map merge

How can I merge maps like below:
val map1 = Map(1 -> "a", 2 -> "b")
val map2 = Map("a" -> "A", "b" -> "B")
After merged.
Merged = Map( 1 -> List("a", "A"), 2 -> List("b", "B"))
Can be List, Set or any other collection who has size attribute.
I'm not sure I understand what are you searching for exactly, but to achieve that for the provided example you could do:
val map1 = Map(1 -> "a", 2 -> "b")
val map2 = Map("a" -> "A", "b" -> "B")
map1.mapValues(value => (value, map2(value)))
However you should be careful to have every value from a as a key in b (I just assumed this happens from the provided example).
Given two maps with value1 as key2
scala> val x = Map(1 -> "a", 2 -> "b")
x: scala.collection.immutable.Map[Int,String] = Map(1 -> a, 2 -> b)
scala> val y = Map("a" -> "A", "b" -> "B")
y: scala.collection.immutable.Map[String,String] = Map(a -> A, b -> B)
Merge as Map(k1 -> List(v1, v2))
scala> val z = x.map { case (k1, v1) => (k1, List(v1, y(v1))) }
z: scala.collection.immutable.Map[Int,List[String]] = Map(1 -> List(a, A), 2 -> List(b, B))
You basically need to get value from first map then lookup the second map, and just create a List out of those (v1, v2).
Try This
scala> val map1 = Map(1 -> "a", 2 -> "b")
map1: scala.collection.immutable.Map[Int,String] = Map(1 -> a, 2 -> b)
scala> val map2 = Map("a" -> "A", "b" -> "B")
map2: scala.collection.immutable.Map[String,String] = Map(a -> A, b -> B)
scala> map1.zip(map2).map(x=>x._1._1 -> List(x._2._1,x._2._2))
res44: scala.collection.immutable.Map[Int,List[String]] = Map(1 -> List(a, A), 2 -> List(b, B))

Scala Map: Combine keys with the same value?

Suppose I have a Map like
val x = Map(1 -> List("a", "b"), 2 -> List("a"),
3 -> List("a", "b"), 4 -> List("a"),
5 -> List("c"))
How would I create from this a new Map where the keys are Lists of keys from x having the same value, e.g., how can I implement
def someFunction(m: Map[Int, List[String]]): Map[List[Int], List[String]] =
// stuff that would turn x into
// Map(List(1, 3) -> List("a", "b"), List(2, 4) -> List("a"), List(5) -> List("c"))
?
You can convert the Map to a List and then use groupBy to aggregate the first element of each tuple:
x.toList.groupBy(_._2).mapValues(_.map(_._1)).map{ case (x, y) => (y, x) }
// res37: scala.collection.immutable.Map[List[Int],List[String]] =
// Map(List(2, 4) -> List(a), List(1, 3) -> List(a, b), List(5) -> List(c))
Or as #Dylan commented, use _.swap to switch the tuples' elements:
x.toList.groupBy(_._2).mapValues(_.map(_._1)).map(_.swap)

How to set value in scala Map?

I am new to scala. I have a Map. I want to set a value in the Map with a particular key. Here is the code I am writing -
var mp: Map[Int, ParticipationStateTransition] = Map.empty[Int, ParticipationStateTransition]
val change: ParticipationStateTransition = new ParticipationStateTransition
mp(ri.userID) = change
The error it is showing me on the third line is -
application does not take parameters
What am I doing wrong? Thanks in advance.
Use .updated :
scala> val m = Map(1 -> 2)
m: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2)
scala> val n = m.updated(1, 3)
n: scala.collection.immutable.Map[Int,Int] = Map(1 -> 3)
scala> m
res0: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2)
scala> n
res1: scala.collection.immutable.Map[Int,Int] = Map(1 -> 3)
Note that scala's Map are immutable, so you need to assign the return value of .updated, it will not change the original map.
If you want to change the map in place, you can use collection.mutable.Map and then
scala> val m = collection.mutable.Map(1 -> 2)
m: scala.collection.mutable.Map[Int,Int] = Map(1 -> 2)
scala> m.update(1, 3)
scala> m
res3: scala.collection.mutable.Map[Int,Int] = Map(1 -> 3)
If you want to set multiple values at once, you can do :
scala> val m = Map(1 -> 2)
m: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2)
scala> val n = m ++ List((1 -> 3), (2 -> 4)) // also accepts an Array, a Map, …
n: scala.collection.immutable.Map[Int,Int] = Map(1 -> 3, 2 -> 4)

Create Map holding a # of appearance for each List element [duplicate]

This question already has answers here:
Count occurrences of each element in a List[List[T]] in Scala
(3 answers)
Closed 9 years ago.
I'm new to Scala.
If I have the following List:
val ls = List("a", "a", "a", "b", "b", "c")
how can I create a Map that holds an number of appearances for every element in the list?
For example the Map for the list above should be:
Map("a" -> 3, "b" -> 2, "c" -> 1)
list.foldLeft(Map[String, Int]() withDefaultValue 0) { (m, x) => m + (x -> (m(x) + 1)) }
snippet in action:
scala> val list = List("a", "a", "b", "c", "c", "a")
list: List[String] = List(a, a, b, c, c, a)
scala> list.foldLeft(Map[String, Int]() withDefaultValue 0) { (m, x) => m + (x -> (1 + m(x))) }
res1: scala.collection.immutable.Map[String,Int] = Map(a -> 3, b -> 1, c -> 2)
(directly based on Count occurrences of each element in a List[List[T]] in Scala)
Not as efficient as Erik's foldLeft solution:
val ls = List("a", "a", "a", "b", "b", "c")
ls.groupBy(identity).mapValues(_.size)
res0: scala.collection.immutable.Map[String,Int] = Map(a -> 3, c -> 1, b -> 2)
With scalaz,
xs foldMap (x => Map(x -> 1))

Composing two maps

Is there a function in Scala to compose two maps or is flatMap a sensible approach?
scala> val caps: Map[String, Int] = Map(("A", 1), ("B", 2))
caps: Map[String,Int] = Map(A -> 1, B -> 2)
scala> val lower: Map[Int, String] = Map((1, "a"), (2, "b"))
lower: Map[Int,String] = Map(1 -> a, 2 -> b)
scala> caps.flatMap {
| case (cap, idx) => Map((cap, lower(idx)))
| }
res1: scala.collection.immutable.Map[String,String] = Map(A -> a, B -> b)
Some syntactic sugar would be great!
If you know lower will contain keys for all the values in caps, you can use mapValues:
scala> caps mapValues lower
res0: scala.collection.immutable.Map[String,String] = Map(A -> a, B -> b)
If you don't want or need a new collection, just a mapping, it's a little more idiomatic to use andThen:
scala> val composed = caps andThen lower
composed: PartialFunction[String,String] = <function1>
scala> composed("A")
res1: String = a
This also assumes there aren't values in caps that aren't mapped in lower.