Scala 按集过滤

Scala filter by 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)

这样做的目的是,如果我有多组表示不同类别的服装,我的输出地图本身不会 "repeat" 在技术上相同的对象上。

感谢任何帮助,谢谢!

所以首先摆脱你的集合实际上是数组的混淆。对于示例的其余部分,我将改用此定义:

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

由于您的 "sets" 实际上是数组,因此这实际上是数组中第一个也用作键的元素。如果你真的使用集合,这段代码仍然可以工作,因为集合实际上有一个 "first element"。它只是高度特定于实现,甚至可能无法确定同一程序的各种执行。至少对于不可变集,它应该在多次调用 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}

注意:集合也是从元素到布尔值的函数,这就是此解决方案有效的原因。

基本思路是使用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

用数字标记每组,然后形成地图以便您查找。地图有应用功能,所以你可以像上面那样使用它。

这段代码解决了问题:

var newMap = map

set.foreach { list =>
  var remove = false
  list.foreach { _key =>
    if (remove) {
      newMap -= _key
    }
    if (newMap.contains(_key)) {
      remove = true
    }

  }
}

I'm completely new at Scala. I have taken this as my first Scala example, please any hints from Scala's Gurus is welcome.

稍微简单一点的版本

set.flatMap(_.find(map.contains).map(y => y -> map(y)))