用于scala集合中元素的复杂分组的内置方法

时间:2015-08-07 01:01:20

标签: scala collections

我正在研究一个问题,我需要使用非传递谓词函数对Scala集合中的项进行分组。例如,我可能有Set(52**, 521*, 5211, 5212)并且还有:

predicate(52**, 521*) = true
predicate(52**, 5211) = true
predicate(52**, 5212) = true    
predicate(521*, 5211) = true
predicate(521*, 5212) = true
predicate(5211, 5212) = false

星星基本上是通配符,可以等于任何东西。

分组的结果应如下所示:

Set(Set(52**,521*,5211), Set(52**,521*,5212))

注意谓词如何适用于组合在一起的所有项目。我希望了解是否有一种内置方法可以帮助实现这种行为。

谓词函数是可交换的。

1 个答案:

答案 0 :(得分:2)

假设您的“谓词”可以是任意函数,那么使用Scala内置方法就有强制解决方案。它只生成元素的所有组合,并检查组合中的每对元素与predicate

def predicate(s1:String, s2:String) =
  Map(
    Set("52**", "521*") -> true,
    Set("52**", "5211") -> true,
    Set("52**", "5212") -> true,
    Set("521*", "5211") -> true,
    Set("521*", "5212") -> true,
    Set("5211", "5212") -> false
  )(Set(s1,s2))

val input = List("52**", "521*", "5211", "5212")

val res = (2 to input.size).flatMap(input.combinations)
  .filter(_.combinations(2).forall {
  case Seq(x1, x2) => predicate(x1, x2)
}).map(_.toSet)

val maximalRes = res.filter(r => 
  !res.exists(x => x != r && r.diff(x).isEmpty))

结果:

res = Vector(Set(52**, 521*), Set(52**, 5211), Set(52**, 5212), Set(521*, 5211), Set(521*, 5212), Set(52**, 521*, 5211), Set(52**, 521*, 5212))
maximalRes = Vector(Set(52**, 521*, 5211), Set(52**, 521*, 5212))

正如我所说,这种方法是强力的,因此非常低效。了解有关predicate函数的更多信息,可能的元素和输入大小将有助于提出更有效的解决方案。