在链接here的问题中,我在Scala中找到了Union的实现:
def union(a: Set, b: Set): Set = i => a(i) || b(i)
Set是类型函数:
type Set = Int => Boolean
现在我明白在Scala中,函数在这里从Int映射到Boolean,我进一步理解了这个语句是如何执行的:
a(i) || b(i)
但我不明白的是'我'在这里。它从何而来?当它找到to sets之间的匹配时,它返回true,如果确实如此,我在哪里过滤它?
答案 0 :(得分:18)
从Set
返回的union
(只是一个函数)需要一些整数作为参数;你必须给它一个任意的名字,以便你可以在函数体中引用它。如果你编写这样的函数可能会更有意义:
def union(a: Set, b: Set): Set = {
(i) => a(i) || b(i)
}
如果你这样写它可能会更有意义:
def union(a: Set, b: Set): Set = {
// The union of two sets is a new function that takes an Int...
def theUnion(i: Int): Boolean = {
// and returns true if EITEHR of the other functions are true
a(i) || b(i)
}
// Now we want to return the NEW function
theUnion
}
同样,i
是任意的,可以用任何变量替换:
def union(a: Set, b: Set): Set = item => a(item) || b(item)
<强> [更新] 强>
因为我们将集合表示为函数,所以不需要迭代以查看它们是否包含数字。例如,这是一个包含-5
以下任何数字的集合:
val belowNegFive: Set = (i) => i < -5
当我们用一个数字调用该函数时,它会告诉我们该数字是否在集合中。请注意,在没有时间我们实际上告诉它集合中的特定数字:
scala> belowNegFive(10)
res0: Boolean = false
scala> belowNegFive(-100)
res1: Boolean = true
scala> belowNegFive(-1)
res2: Boolean = false
这是另一套包含50
和100
之间任意数字的数据集:
val fiftyToHundred: Set = (i) => i >= 50 && i <= 100
scala> fiftyToHundred(50)
res3: Boolean = true
scala> fiftyToHundred(100)
res4: Boolean = true
scala> fiftyToHundred(75)
res5: Boolean = true
scala> fiftyToHundred(49)
res6: Boolean = false
现在,集belowNegFive
和fiftyToHundred
的联盟将包含 以下-5
的任何数字{/ 1}}和50
之间的>或。我们可以通过返回 new 函数轻松地在代码中表示这一点,如果其他两个函数的 返回true,则该函数本身返回true。
100
您问题中的scala> val unionOfBoth: Set = (i) => belowNegFive(i) || fiftyToHundred(i)
unionOfBoth: Int => Boolean = <function1>
scala> unionOfBoth(-10)
res7: Boolean = true
scala> unionOfBoth(50)
res8: Boolean = true
scala> unionOfBoth(0)
res9: Boolean = false
函数只是一种将此模式一般应用于任何两个集合的方法。
答案 1 :(得分:11)
假设我们有一个名为SoSet
的对象,由
object SoSet {
type Set = Int => Boolean
val a : Set = ???
val b : Set = ???
def isItem(item : Int) = a(item) || b(item)
}
isItem
的签名由Int => Boolean
提供,即Set
。到现在为止还挺好。
但是现在我们只想返回函数 isItem
(即Set
)。
所以我们为此定义union
函数(现在没有参数。我们稍后会添加它。)
object SoSet {
//..
def union : Set = isItem // returns the function isItem
}
现在让我们将isItem
重构为anonymous function。
object SoSet {
//..
def union : Set = {
(item : Int) => a(item) || b(item)
}
}
允许Set a and b
从object SoSet
移至参数def union
。将item
重构为i
。
object SoSet {
type Set = Int => Boolean
def union(a : Set, b : Set) : Set = (i : Int) => a(i) || b(i)
}
更新
val s1 = Set(1, 2, 3)
val s2 = Set(2, 3, 4)
val s3 = union(s1, s2) // returns the function.. Int => Boolean = <function1>
s3(2) // invokes the function & checks if 2 is present in the union
答案 2 :(得分:1)
当它找到to sets之间的匹配时,它返回true,如果确实如此,我在哪里过滤它?
union
在两个集合之间找不到匹配项,它会创建一个包含值的新集合
两套。例如:
val a = (i) => i == 2 // a contains 2 as a(2) == True
val b = (i) => i == 5 // b contains 5 as b(5) == True
val u = union(a, b) // u contains 2 and 5 as u(2) == True and u(5) == True
所以'过滤'恰好在路上发生。这个函数不会迭代每个集合,过滤特定的东西,它只返回两个函数的组合,然后可以执行以查询实际值。
查询union的值的示例:
val a = (i) => i == 2
val b = (i) => i == 5
val u = union(a, b)
for(i <- 1 to 10 if u(i)) yield i // returns Vector(2, 5)
是的,这不是在集合中存储值的最佳方式,因为您必须通过检查值 猜测,但它是一个很好的方式来演示组合函数如何添加复杂的功能 编写非常复杂的代码。
答案 3 :(得分:0)
您可以实现这样的联合功能:
def union[A](set1: Set[A], set2:Set[A]):Set[A] = {
set1.foldLeft(set2)((set, elem) => set + elem)
}
或
def union[A](set1: Set[A], set2:Set[A]):Set[A] = {
set1.flatMap(elem => set2 + elem)
}
这些将是通用的,因此您可以将其用于任何类型的集