说我有一张看起来像这样的地图
val map = Map("Shoes" -> 1, "heels" -> 2, "sneakers" -> 3, "dress" -> 4, "jeans" -> 5, "boyfriend jeans" -> 6)
我也有一个看起来像这样的集合或集合:
val set = Array(Array("Shoes", "heels", "sneakers"), Array("dress", "maxi dress"), Array("jeans", "boyfriend jeans", "destroyed jeans"))
我想在我的地图上执行过滤操作,以便每个设置中只有一个元素保留。预期的输出应该是这样的:
map = Map("Shoes" -> 1, "dress" -> 4 ,"jeans" -> 5)
这样做的目的是,如果我有多个指示不同类别的服装的集合,我的输出映射不会在技术上“重复”它们自己相同的对象。
感谢任何帮助,谢谢!
答案 0 :(得分:3)
所以首先要摆脱你的集合实际上是数组的混乱。对于示例的其余部分,我将使用此定义:
val arrays = Array(Array("Shoes", "heels", "sneakers"), Array("dress", "maxi dress"), Array("jeans", "boyfriend jeans", "destroyed jeans"))
所以从某种意义上说,你有一个等效对象数组的数组,并希望删除除了其中一个之外的所有对象?
首先,您必须找到数组中的哪些元素实际用作mep中的键。所以我们只过滤掉所有未用作键的元素:
array.filter(map.keySet)
现在,我们必须选择一个元素。正如你所说,我们只是采取第一个:
array.filter(map.keySet).head
由于您的“集合”实际上是数组,因此这实际上是数组中第一个也用作键的元素。如果你实际上使用集合,这个代码仍然可以工作,因为集合实际上有一个“第一个元素”。它只是高度实现特定的,甚至可能不是同一程序的各种执行的确定性。至少对于不可变集合,它应该是对几个调用头的确定性,即,你应该总是得到相同的元素。
我们实际上对所有其他元素感兴趣,而不是第一个元素,因为我们想要从地图中删除它们:
array.filter(map.keySet).tail
现在,我们只需从地图中删除它们:
map -- array.filter(map.keySet).tail
为所有阵列做到这一点:
map -- arrays.flatMap(_.filter(map.keySet).tail)
只要数组脱节,这就可以正常工作。如果不是,我们就不能在每个步骤中采用初始映射来过滤数组。相反,我们必须使用一个数组来计算一个新的地图,然后从下一个数据的结果开始下一个,依此类推。幸运的是,我们不需要做太多事情:
arrays.foldLeft(map){(m,a) => m -- a.filter(m.keySet).tail}
注意:集合也是从元素到布尔值的函数,这就是为什么这个解决方案有效。
答案 1 :(得分:2)
基本思路是使用groupBy
。像
map.groupBy{ case (k,v) => g(k) }.
map{ case (_, kvs) => kvs.head }
这是将类似事物分组的一般方法(使用某个函数g
)。现在的问题是如何制作您需要的g
。一种方法是
val g = set.zipWithIndex.
flatMap{ case (a, i) => a.map(x => x -> i) }.
toMap
用数字标记每个集合,然后形成一个地图,以便您可以查找它。地图具有应用功能,因此您可以按上述方式使用它。
答案 2 :(得分:2)
此代码解决了问题:
var newMap = map
set.foreach { list =>
var remove = false
list.foreach { _key =>
if (remove) {
newMap -= _key
}
if (newMap.contains(_key)) {
remove = true
}
}
}
我是斯卡拉的全新人物。我把它作为我的第一个Scala 例如,欢迎来自斯卡拉大师的任何提示。
答案 3 :(得分:1)
稍微简单的版本
set.flatMap(_.find(map.contains).map(y => y -> map(y)))