简体   繁体   English

将列表元素与所有其他元素进行比较

[英]Compare an element of a list against all other elements

Say I have a Scala list, 说我有一个Scala列表,

val list : List[Set[Int]] = List(set1, set2, set3, set4)

where each element of my list is a set of integers. 我列表中的每个元素都是一组整数。

I'm looking for an elegant way to create a list where each element of my list is compared against all others. 我在寻找一种优雅的方式来创建在我的列表中的每个元素对所有其他人相比的列表。 For example, I might want to generate a list where each element (set) contains only elements not contained in any other element of the list. 例如,我可能想要生成一个列表,其中每个元素(集合)仅包含未包含在列表的任何其他元素中的元素。

eg I have some function: 例如,我有一些功能:

def f(element : Set[Int], rest_of_list : List[Set[Int]]) : Set[Int]

and I want to do something similar to list.map(f(_, rest_of_list)) without having to construct rest_of_list for each element. 我想做类似于list.map(f(_, rest_of_list))事情list.map(f(_, rest_of_list))而不必为每个元素构造rest_of_list The only way I can think of doing it right now is to use slice , which makes it very ugly and inefficient, imo. 我现在能想到的唯一方法是使用slice ,这使得它非常丑陋和低效,imo。

You can use diff instead of slice : 您可以使用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 works here since it only removes one instance of the element, and Set[Int] has a nice equals method: 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))

So, to this maps a set to the list of all other sets in the list: 因此,为此,将一个集映射到列表中所有其他集的列表:

val setWithOthers = list.map(set => set -> (list diff List(set)))
val setWithOthers = (list, list.map(list diff List(_))).zipped.toList //equivalent, less efficient

So if you wanted to map your function f across elements of list , you could do: 因此,如果您想要在list元素之间映射函数f ,您可以:

setsWithOthers.map { case(set, others) => f(set, others) }
setsWithOthers.map(kvp => f(kvp._1, kvp._2))
setsWithOthers.map((f _).tupled)

You could also create the full multiset which keeps track of how many times each element appears. 您还可以创建完整的多重集,跟踪每个元素出现的次数。 Then, in each iteration of the loop, you can "subtract" a set from the full multiset: 然后,在循环的每次迭代中,您可以从完整的multiset“减去”一个集合:

val multiset = list.flatten.groupBy(identity).mapValues(_.length)

I don't know if it is as elegant as you want but a more general way that you can replace 'f' with anything: 我不知道它是否像你想要的那样优雅,但更通用的方式是你可以用任何东西替换'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
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM