Scala 中两个集合的并集

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19204631/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 05:43:54  来源:igfitidea点击:

Union of two sets in Scala

scalafunctional-programming

提问by user1343318

From the question linked here, I found this implementation of Union in Scala:

这里链接的问题中,我在 Scala 中找到了 Union 的这个实现:

def union(a: Set, b: Set): Set = i => a(i) || b(i)

And Set is a function of type:

而 Set 是一个类型的函数:

type Set = Int => Boolean

Now I understand that in Scala, a function is mapped from Int to Boolean here, and I further understand how this statement is executed:

现在我明白了在Scala中,一个函数在这里从Int映射到Boolean,我进一步理解了这个语句是如何执行的:

a(i) || b(i)

But what I don't understand is what is 'i' here. Where does it come from? And when it finds a match between to sets, it returns true, if it indeed does, where do I filter it?

但我不明白的是这里的“我”是什么。它从何而来?当它找到集合之间的匹配时,它返回true,如果确实如此,我在哪里过滤它?

采纳答案by Shrey

Let say we have object called SoSetgiven by

假设我们有被称为SoSet给定的对象

object SoSet {
    type Set = Int => Boolean
    val a : Set = ???
    val b : Set = ???
    def isItem(item : Int) = a(item) || b(item)
}

The signature of isItemis given by Int => Booleanwhich is a Set. So far so good.

的签名isItemInt => Booleanwhich给出Set。到现在为止还挺好。

But now we just want to return the functionisItem(i.e. a Set).

但是现在我们只想返回函数isItem(即 a Set)。

So lets define unionfunction for this (There are no parameters right now. We will add it later).

所以让我们union为此定义函数(现在没有参数。我们稍后会添加它)。

object SoSet {
    //..   
     def union : Set = isItem // returns the function isItem
}

Now lets refactor the isIteminto a anonymous function.

现在让我们将 重构isItem匿名函数

object SoSet {
    //..   
    def union : Set = {
      (item : Int) => a(item) || b(item)
    }
}

Lets move Set a and bfrom object SoSetto parameters of def union. Refactor itemto i.

让我们Set a and bobject SoSet到 的参数def union。重构itemi.

object SoSet { 
   type Set = Int => Boolean
   def union(a : Set, b : Set) : Set = (i : Int) => a(i) || b(i)
}

UPDATE

更新

 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     

回答by Michelle Tilley

The Set(which is just a function) that gets returned from uniontakes some integer as a parameter; you must give it an arbitrary name so that you can refer to it in the function body. It may make more sense if you write the function like this:

返回的Set(这只是一个函数)union以一些整数作为参数;你必须给它一个任意的名字,以便你可以在函数体中引用它。如果你这样写函数可能更有意义:

def union(a: Set, b: Set): Set = {
  (i) => a(i) || b(i)
}

It may make even more sense if you write it like this:

如果你这样写可能更有意义:

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
}

Again, iis arbitrary and could be replaced with any variable:

同样,i是任意的,可以用任何变量替换:

def union(a: Set, b: Set): Set = item => a(item) || b(item)

[Update]

[更新]

Because we're representing sets as functions, there's no need to iterate to see if they contain a number. For example, here's a set that contains any number below -5:

因为我们将集合表示为函数,所以不需要迭代查看它们是否包含数字。例如,这是一个包含以下任意数字的集合-5

val belowNegFive: Set = (i) => i < -5

When we call that function with a number, it will tell us if that number is in the set. Note that at no timedid we actually tell it the specific numbersthat were in the set:

当我们用一个数字调用该函数时,它会告诉我们该数字是否在集合中。请注意,我们实际上从未告诉它集合中的具体数字

scala> belowNegFive(10)
res0: Boolean = false

scala> belowNegFive(-100)
res1: Boolean = true

scala> belowNegFive(-1)
res2: Boolean = false

Here's another set that includes any number between 50and 100:

这是另一组,包括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

Now, a unionof the sets belowNegFiveand fiftyToHundredwould contain any number that is eitherbelow -5orbetween 50and 100. We can easily represent this in code by returning a newfunction which itself returns true if eitherof the other two functions returns true.

现在,联盟中套belowNegFivefiftyToHundred将包含任何数字,无论是低于-5之间50100。我们可以通过返回一个函数来轻松地在代码中表示这一点,如果其他两个函数中的任何一个返回 true,则该函数本身返回 true。

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

The unionfunction from your question is just a way of applying this pattern generically over anytwo sets.

union您问题中的函数只是将这种模式一般应用于任何两组的一种方式。

回答by nemo

And when it finds a match between to sets, it returns true, if it indeed does, where do I filter it?

当它找到集合之间的匹配时,它返回true,如果确实如此,我在哪里过滤它?

uniondoes not find a match between two sets, it creates a new set which contains the values of both sets. Example:

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

So the 'filtering' just happens on the way. This function is not iterating over each set, filtering specific things out, it just returns a combination of two functions which then can executed later to query for the actual values.

所以“过滤”只是在途中发生。这个函数不是迭代每个集合,过滤掉特定的东西,它只是返回两个函数的组合,然后可以稍后执行以查询实际值。

Example of querying the values of a 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)

And yes, this is not an optimal way of storing values in sets as you have to check values by guessing but it is a good way to demonstrate how combining functions adds complex functionality without writing very complex code.

是的,这不是将值存储在集合中的最佳方式,因为您必须通过猜测来检查值,但它是一种很好的方式来演示组合函数如何在不编写非常复杂的代码的情况下添加复杂的功能。

回答by Denys Lobur

You can implement a union function like this:

你可以实现一个像这样的联合函数:

def union[A](set1: Set[A], set2:Set[A]):Set[A] = {
    set1.foldLeft(set2)((set, elem) => set + elem)
}

or

或者

def union[A](set1: Set[A], set2:Set[A]):Set[A] = {
    set1.flatMap(elem => set2 + elem)
}

These will be generic so you can use it for sets of any type

这些将是通用的,因此您可以将其用于任何类型的集合