Scala two map merge - scala

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))

Related

Removing elements from a map of type (Int, ListBuffer(Int))

I have LinkedHashMaps of type:
val map1 = LinkedHashMap(1 -> 1, 2 -> (1,2), 3 -> (1,2,3))
val map2 = LinkedHashMap(2 -> 2, 3 -> (2,3), 5 -> (2,3,5))
where the integers are nodes's ids of a graph, and the list is the path to that node. I want to implement the case of deleting a node. Suppose I want to delete node 3, I have to do two actions: remove the element with key = 3 in every map, remove the elements which have 3 in their list. How to do it in scala?
If you define you map like you have,
val map1 = LinkedHashMap(1 -> 1, 2 -> (1,2), 3 -> (1,2,3))
You do not have key: Int and value: List[Int] but you have key: Int and values: Any.
scala> val map1 = LinkedHashMap(1 -> 1, 2 -> (1,2), 3 -> (1,2,3))
// map1: scala.collection.mutable.LinkedHashMap[Int,Any] = Map(1 -> 1, 2 -> (1,2), 3 -> (1,2,3))
To match your requirement, you should define your map like following,
scala> val map1 = LinkedHashMap(1 -> List(1), 2 -> List(1,2), 3 -> List(1,2,3))
// map1: scala.collection.mutable.LinkedHashMap[Int,List[Int]] = Map(1 -> List(1), 2 -> List(1, 2), 3 -> List(1, 2, 3))
Now, if you want to delete a node 3,
scala> val map2 = map1.filter({
| case (key, list) => key != 3 && !list.contains(3)
| })
// map2: scala.collection.mutable.LinkedHashMap[Int,List[Int]] = Map(1 -> List(1), 2 -> List(1, 2))

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)

Scala - Drop all mappings whose keys are not in a given set

What is the idiomatic way to compute a map whose mappings are the mappings of another map, without the mappings whose keys are members of a given set?
For example, from the given set and map below:
Map(A -> v, B -> w, C -> x, D -> y, E -> z)
Set(A, C, E)
our function would yield:
Map(B -> w, D -> y)
You can use the -- method from Map
def --(xs: GenTraversableOnce[A]): Map[A, B]
Creates a new collection from this collection by removing all elements
of another collection.
scala> val map = Map("A" -> "v", "B" -> "w", "C" -> "x", "D" -> "y", "E" -> "z")
map: scala.collection.immutable.Map[String,String] = Map(E -> z, A -> v, B -> w, C -> x, D -> y)
scala> val set = Set("A", "C", "E")
set: scala.collection.immutable.Set[String] = Set(A, C, E)
scala> val filter = map -- set
filter: scala.collection.immutable.Map[String,String] = Map(B -> w, D -> y)
Just filter it:
val map = Map("A" -> "v", "B" -> "w", "C" -> "x", "D" -> "y", "E" -> "z")
val set = Set("A", "C", "E")
map.filterKeys(!set.contains(_))
Results in:
res0: scala.collection.immutable.Map[String,String] = Map(B -> w, D -> y)

How to create a map out of two lists?

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)

Remove an entry from a Map and return a new Map

I want to check if a Map doesn't contain empty values. If the value is empty it shouldn't includen in the new Map.
I tried something like:
val newmap = map.map{ entry => if(!entry._2.isEmpty()) Map(entry._1 -> entry._2)}
This does exactly do what I want, but it is not very nice. Is there a better solution?
scala> Map(1 -> List(3, 4), 2 -> Nil, 3 -> List(11))
res2: scala.collection.immutable.Map[Int,List[Int]] = Map(1 -> List(3, 4), 2 -> List(), 3 -> List(11))
scala> res2.filter(_._2.nonEmpty)
res3: scala.collection.immutable.Map[Int,List[Int]] = Map(1 -> List(3, 4), 3 -> List(11))
scala>
You mean empty as in null?
scala> val map = collection.immutable.HashMap[Int, String] (1 -> "a", 2-> "b", 3 -> null)
map: scala.collection.immutable.HashMap[Int,String] = Map(1 -> a, 2 -> b, 3 -> null)
scala> val newmap=map filter (_._2 != null)
newmap: scala.collection.immutable.HashMap[Int,String] = Map(1 -> a, 2 -> b)
EDIT: dang... #missingfaktor beat me to it... :)