Say I have a Scala list,
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. The only way I can think of doing it right now is to use slice
, which makes it very ugly and inefficient, imo.
You can use diff
instead of 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:
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:
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:
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:
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
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.