说我有一个Scala列表,
val list : List[Set[Int]] = List(set1, set2, set3, set4)
其中列表的每个元素都是一组整数。
我正在寻找一种优雅的方式来创建一个列表,其中列表的每个元素都与所有其他元素进行比较。例如,我可能想要生成一个列表,其中每个元素(集合)仅包含未包含在列表的任何其他元素中的元素。
例如我有一些功能:
def f(element : Set[Int], rest_of_list : List[Set[Int]]) : Set[Int]
我希望做一些与list.map(f(_, rest_of_list))
类似的事情,而不必为每个元素构建rest_of_list
。我现在能想到的唯一方法是使用slice
,这会让它变得非常丑陋和低效,imo。
答案 0 :(得分:2)
您可以使用diff
代替slice
:
list.map(set => set diff (list diff List(set)).flatten.toSet)
//Alternative with filterNot
list.map(set => set.filterNot((list diff List(set)).flatten.contains))
diff
在这里工作,因为它只删除了元素的一个实例,Set[Int]
有一个很好的equals
方法:
List(Set(1), Set(1, 2)) diff List(Set(1)) //List(Set(1, 2))
List(Set(1), Set(1)) diff List(Set(1)) //List(Set(1))
因此,要将一个集映射到列表中所有其他集的列表:
val setWithOthers = list.map(set => set -> (list diff List(set)))
val setWithOthers = (list, list.map(list diff List(_))).zipped.toList //equivalent, less efficient
因此,如果您希望在f
的元素之间映射函数list
,您可以这样做:
setsWithOthers.map { case(set, others) => f(set, others) }
setsWithOthers.map(kvp => f(kvp._1, kvp._2))
setsWithOthers.map((f _).tupled)
您还可以创建完整的多重集,用于跟踪每个元素出现的次数。然后,在循环的每次迭代中,您可以减去"完整的multiset中的一组:
val multiset = list.flatten.groupBy(identity).mapValues(_.length)
答案 1 :(得分:1)
我不知道它是否像你想要的那样优雅,但更通用的方式是你可以用任何东西替换'f':
val list = List(Set(1,2,3,4),Set(1,2),Set(1,3))
list.map(e => f(e,list.filterNot(_==e)))
//res0: List[Set[Int]] = List(Set(4), Set(), Set())
def f(element : Set[Int], rest_of_list : List[Set[Int]]) : Set[Int] = {
(element.toList diff rest_of_list.flatten.toList).toSet
}