【问题标题】:Set operations (union, intersection) on Swift array?在 Swift 数组上设置操作(联合、交集)?
【发布时间】:2014-08-26 16:07:11
【问题描述】:

是否有任何标准库调用可以用来对两个数组执行集合操作,或者自己实现这样的逻辑(理想情况下,功能和效率都尽可能)?

【问题讨论】:

  • 如果你想自己做一个集合,可以在字典之上实现。
  • @CodaFi 你的意思是用keys来保证唯一性吗?
  • 你能用`Dictionary吗?

标签: functional-programming swift set-operations


【解决方案1】:

没有任何标准库调用,但您可能想查看ExSwift 库。它包含了一系列关于数组的新函数,包括差分、交集和并集。

【讨论】:

  • 警告:我在 Swift 1.x 上一直使用 ExSwift 没有问题,但在 Swift 2.x 上似乎很糟糕,并且在撰写本文时几个月内还没有更新.有很多分叉可能会受到更多关注。
【解决方案2】:

您可能希望遵循与 Objective-C 相同的模式,后者也缺少此类操作,但有一个简单的解决方法:

how to intersect two arrays in objective C?

【讨论】:

    【解决方案3】:

    是的,Swift 有 Set 类。

    let array1 = ["a", "b", "c"]
    let array2 = ["a", "b", "d"]
    
    let set1:Set<String> = Set(array1)
    let set2:Set<String> = Set(array2)
    

    Swift 3.0+ 可以对集合进行如下操作:

    firstSet.union(secondSet)// Union of two sets
    firstSet.intersection(secondSet)// Intersection of two sets
    firstSet.symmetricDifference(secondSet)// exclusiveOr
    

    Swift 2.0 可以计算数组参数:

    set1.union(array2)       // {"a", "b", "c", "d"} 
    set1.intersect(array2)   // {"a", "b"}
    set1.subtract(array2)    // {"c"}
    set1.exclusiveOr(array2) // {"c", "d"}
    

    Swift 1.2+ 可以在集合上计算:

    set1.union(set2)        // {"a", "b", "c", "d"}
    set1.intersect(set2)    // {"a", "b"}
    set1.subtract(set2)     // {"c"}
    set1.exclusiveOr(set2)  // {"c", "d"}
    

    如果您使用自定义结构,则需要实现 Hashable。

    感谢 cmets 中的 Michael Stern 提供 Swift 2.0 更新。

    感谢 cmets 中的 Amjad Husseini 提供 Hashable 信息。

    【讨论】:

    • 请注意,至少从 Swift 2.0 开始,您可以将数组作为参数传递给这些函数。因此,set1.union(array2)set1.exclusiveOr(array2) 都是合法的,除了上面显示的形式。
    • 如果要相交5个数组怎么办?还是6?如果数组数量未知怎么办?
    • @Nathan 取决于设置操作。例如,集合并集和集合交集是可交换的和关联的,因此您可以使用迭代或链接来处理多个集合。或者您可以创建使用 var args 的自定义方法,例如 Set union_all(...) 和 intersect_all(...)。
    • 如果您的数组包含重复值怎么办,例如确定 $0 是否是 $1 的字谜,其中输入字符可能有重复的字母?
    • 如果你使用自定义结构,你必须符合 Hashable,如果你有一个复杂的结构,这可能会很烦人
    【解决方案4】:

    我所知道的最有效的方法是使用 godel 数。 Google for godel 编码。

    想法是这样的。假设您有 N 个可能的数字,并且需要将它们组合起来。例如,N=100,000 并且想要制作 {1,2,3}、{5,88,19000} 等集合。

    我们的想法是将 N 个素数列表保存在内存中,对于给定的集合 {a, b, c, ...},您将其编码为

     prime[a]*prime[b]*prime[c]*...
    

    因此,您将集合编码为 BigNumber。 BigNumbers 的运算尽管比 Integers 的运算慢,但仍然非常快。

    要合并2组A,B,你拿

      UNITE(A, B) = lcm(a, b)
    

    A 和 B 的最小公倍数,因为 A 和 B 是集合并且都是数字。

    为了让你走的路口

     INTERSECT(A, B) = gcd (a, b)
    

    最大公约数。

    等等。

    这种编码叫做godelization,你可以google一下,所有用弗雷格逻辑写的算术语言都可以用数字编码。

    要获取操作is-member?很简单——

    ISMEMBER(x, S) = remainder(s,x)==0
    

    要获得红衣主教有点复杂--

    CARDINAL(S) = # of prime factors in s
    

    你分解代表素数乘积中集合的数字 S 并添加它们的指数。如果集合不允许重复,您将拥有所有指数 1。

    【讨论】:

      猜你喜欢
      • 2011-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-22
      • 2020-03-18
      • 1970-01-01
      • 2020-12-22
      相关资源
      最近更新 更多