根据布尔表达式过滤集合集

时间:2015-03-21 14:51:50

标签: scala

我有一组如下:

val s =  Set(Set(), Set(1, 3), Set(2), Set(1, 2), Set(2, 3),
  Set(3), Set(1, 2, 3), Set(1))

我想以类似于这个的方式过滤:

s.filter(subset => subset contains !1 && 2)

其中!1 && 2将是一些提供给我的任意布尔表达式。

我会从中回来:

Set(Set(2), Set(2, 3))

为了示例,我选择Int,但它会是一些任意类型。

非常感谢任何帮助,谢谢。

4 个答案:

答案 0 :(得分:1)

您的问题并不清楚“公式”是什么意思。但是,您似乎想要以某种方式参数化filter操作。

在Scala中,我们通常通过传递代码块来实现。例如,在这个(简单的)示例中,keepdiscard是您的两个“公式”:

def processSet[T](s: Set[Set[T]], keep: => T, discard: => T): Set[Set[T]] = {
  s.filter { subset => (subset contains keep) && !(subset contains discard) }
}

然后您可以按如下方式调用该函数:

processSet(Set(Set(10, 20), Set(1, 2), Set(10, 100), Set(10, 20, 30)), 10, 30)
// returns: Set(Set(10, 20), Set(10, 100))

我不确定这是否接近你想要的东西。

答案 1 :(得分:1)

对于问题中的具体示例,您将关闭。您只需要将测试分开为1和2.另外,由于创建值s的方式,您必须使用toSet显式转换子集:

val s = Set(Set(), Set(1, 3), Set(2), Set(1, 2), Set(2, 3), 
            Set(3), Set(1, 2, 3), Set(1))

s.filter{ subset => 
    !(subset.toSet contains 1) && (subset.toSet contains 2)
}

如果显式转换不合适,您可以为s提供类型,如下列其中一个答案:

val s:Set[Set[Int]] = Set(Set(), Set(1, 3), Set(2), Set(1, 2), Set(2, 3), 
                          Set(3), Set(1, 2, 3), Set(1))

s.filter{ subset => 
    !(subset contains 1) && (subset contains 2)
}

只要filter收到一个返回Boolean值的函数(上面是anonymous function),您的方法就可以用于任意公式" 。

参数化过滤器的一种有用方法是使用curried functions

def requirements(x: Int, y: Int)(subset: Set[Int]): Boolean = {
    !(subset contains x) && (subset contains 2)
}

s.filter{ requirements(1, 2)_ }

答案 2 :(得分:0)

这对我有用(scala 2.11.4):

val s:Set[Set[Int]] = Set(Set(), Set(1, 3), Set(2), Set(1, 2), Set(2, 3),Set(3), Set(1, 2, 3), Set(1))

s.filter(subset => !subset.contains(1) && subset.contains(2))

答案 3 :(得分:0)

我使用spire' Bool来完成工作:

import spire.algebra._
import spire.implicits._

object Main {
  def main(args: Array[String]): Unit = {
    implicit def PredicateBooleanAlgebra[T] = new Bool[T => Boolean] {
      def one: T => Boolean = _ => true
      def zero: T => Boolean = _ => false
      def and(a: T => Boolean, b: T => Boolean): T => Boolean = x => a(x) && b(x)
      def or(a: T => Boolean, b: T => Boolean): T => Boolean = x => a(x) || b(x)
      def complement(a: T => Boolean) = x => !a(x)
    }

    def contains1(s: Set[Int]) = s contains 1
    def contains2(s: Set[Int]) = s contains 2

    val s = Set(1, 2, 3).subsets.map(_.toSet).toSet
    println(s.filter(~(contains1 _) & (contains2 _)))
  }
}