Scala按设置过滤

时间:2016-02-05 18:19:23

标签: scala dictionary filter set

说我有一张看起来像这样的地图

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)

这样做的目的是,如果我有多个指示不同类别的服装的集合,我的输出映射不会在技术上“重复”它们自己相同的对象。

感谢任何帮助,谢谢!

4 个答案:

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