在 Swift 数组上设置操作(联合、交集)?

Posted

技术标签:

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

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

【问题讨论】:

如果你想自己做一个集合,可以在字典之上实现。 @CodaFi 你的意思是用keys来保证唯一性吗? 你能用`Dictionary吗? 【参考方案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。

【讨论】:

以上是关于在 Swift 数组上设置操作(联合、交集)?的主要内容,如果未能解决你的问题,请参考以下文章

Linq 数据操作,两个数组求差交集并集

并查集详解

JS数组操作(扁平化去重排序交集并集差集二分查找峰值位置)

JS数组操作(扁平化去重排序交集并集差集)

数组区间操作,数组中重复数相关

ado.net 和 dapper 之间的交集/联合是啥?