使用 HOF 反转以 A Set 作为其值的 Map
Reverse a Map which has A Set as its value using HOF
我正在尝试反转以字符串作为键并以一组数字作为值的映射
我的目标是创建一个列表,其中包含一个数字元组和一个在值集中具有相同数字的字符串列表
到目前为止我有这个:
def flipMap(toFlip: Map[String, Set[Int]]): List[(Int, List[String])] = {
toFlip.flatMap(_._2).map(x => (x, toFlip.keys.toList)).toList
}
但它只是将每个字符串分配给每个 Int
val map = Map(
"A" -> Set(1,2),
"B" -> Set(2,3)
)
应该产生:
List((1, List(A)), (2, List(A, B)), (3, List(B)))
但正在生产:
List((1, List(A, B)), (2, List(A, B)), (3, List(A, B)))
这有效,但它并不是您可能需要的,您可能需要进行一些转换才能获得所需的确切数据类型:
toFlip.foldLeft(Map.empty[Int, Set[String]]) {
case (acc, (key, numbersSet)) =>
numbersSet.foldLeft(acc) {
(updatingMap, newNumber) =>
updatingMap.updatedWith(newNumber) {
case Some(existingSet) => Some(existingSet + key)
case None => Some(Set(key))
}
}
}
我使用 Set
来避免在内部列表中重复插入键,并使用 Map
来更好地查找而不是外部列表。
// both scala2 & scala3
scala> map.flatten{ case(k, s) => s.map(v => (k, v)) }.groupMapReduce{ case(k, v) => v }{case(k, v) => List(k)}{ _ ++ _ }
val res0: Map[Int, List[String]] = Map(1 -> List(A), 2 -> List(A, B), 3 -> List(B))
// scala3 only
scala> map.flatten((k, s) => s.map(v => (k, v))).groupMapReduce((k, v) => v)((k, v) => List(k))( _ ++ _ )
val res1: Map[Int, List[String]] = Map(1 -> List(A), 2 -> List(A, B), 3 -> List(B))
你可以这样做:
def flipMap(toFlip: Map[String, Set[Int]]): List[(Int, List[String])] =
toFlip
.toList
.flatMap {
case (key, values) =>
values.map(value => value -> key)
}.groupMap(_._1)(_._2)
.view
.mapValues(_.distinct)
.toList
注意,我个人会 return Map
而不是 List
或者如果您在范围内有 cats。
def flipMap(toFlip: Map[String, Set[Int]]): Map[Int, Set[String]] =
toFlip.view.flatMap {
case (key, values) =>
values.map(value => Map(value -> Set(key)))
}.toList.combineAll
我正在尝试反转以字符串作为键并以一组数字作为值的映射
我的目标是创建一个列表,其中包含一个数字元组和一个在值集中具有相同数字的字符串列表
到目前为止我有这个:
def flipMap(toFlip: Map[String, Set[Int]]): List[(Int, List[String])] = {
toFlip.flatMap(_._2).map(x => (x, toFlip.keys.toList)).toList
}
但它只是将每个字符串分配给每个 Int
val map = Map(
"A" -> Set(1,2),
"B" -> Set(2,3)
)
应该产生:
List((1, List(A)), (2, List(A, B)), (3, List(B)))
但正在生产:
List((1, List(A, B)), (2, List(A, B)), (3, List(A, B)))
这有效,但它并不是您可能需要的,您可能需要进行一些转换才能获得所需的确切数据类型:
toFlip.foldLeft(Map.empty[Int, Set[String]]) {
case (acc, (key, numbersSet)) =>
numbersSet.foldLeft(acc) {
(updatingMap, newNumber) =>
updatingMap.updatedWith(newNumber) {
case Some(existingSet) => Some(existingSet + key)
case None => Some(Set(key))
}
}
}
我使用 Set
来避免在内部列表中重复插入键,并使用 Map
来更好地查找而不是外部列表。
// both scala2 & scala3
scala> map.flatten{ case(k, s) => s.map(v => (k, v)) }.groupMapReduce{ case(k, v) => v }{case(k, v) => List(k)}{ _ ++ _ }
val res0: Map[Int, List[String]] = Map(1 -> List(A), 2 -> List(A, B), 3 -> List(B))
// scala3 only
scala> map.flatten((k, s) => s.map(v => (k, v))).groupMapReduce((k, v) => v)((k, v) => List(k))( _ ++ _ )
val res1: Map[Int, List[String]] = Map(1 -> List(A), 2 -> List(A, B), 3 -> List(B))
你可以这样做:
def flipMap(toFlip: Map[String, Set[Int]]): List[(Int, List[String])] =
toFlip
.toList
.flatMap {
case (key, values) =>
values.map(value => value -> key)
}.groupMap(_._1)(_._2)
.view
.mapValues(_.distinct)
.toList
注意,我个人会 return Map
而不是 List
或者如果您在范围内有 cats。
def flipMap(toFlip: Map[String, Set[Int]]): Map[Int, Set[String]] =
toFlip.view.flatMap {
case (key, values) =>
values.map(value => Map(value -> Set(key)))
}.toList.combineAll