Reputation: 691
I'm working on a problem where I need to group the items in a Scala collection by using a non-transitive predicate function. As an example, I might have a Set(52**, 521*, 5211, 5212)
and also have:
predicate(52**, 521*) = true
predicate(52**, 5211) = true
predicate(52**, 5212) = true
predicate(521*, 5211) = true
predicate(521*, 5212) = true
predicate(5211, 5212) = false
The stars are basically wildcards and can be equal to anything.
The result of grouping should look like:
Set(Set(52**,521*,5211), Set(52**,521*,5212))
Notice how the predicate holds true for all the items grouped together. I'm hoping to learn if there is a built-in method that can help achieve such behavior.
The predicate function is commutative.
Upvotes: 3
Views: 115
Reputation: 10882
Assuming that your "predicate" can be arbitrary function, there is bruteforce solution using Scala built-in methods. It just generates all combinations of elements and checks every pair of elements within the combination against 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))
Result:
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))
As I said, this approach is bruteforce, hence very inefficient. Knowing more about your predicate
function, possible elements and input size will help to come up with more efficient solution.
Upvotes: 2