Swift - 性能明智 - 比较两个数组并获得每个数组的差异并在两者中共同使用

时间:2017-07-09 09:43:15

标签: ios arrays swift performance sorting

希望你过得愉快。

我正在尝试了解执行以下操作的最快方法

假设我有这两个type name regid irq sysbus lkmc_platform_device 0x101e9000 18

Arrays

我想得到一个输出:

1)var firstArray = ["a","b","c"] var secondArray = ["a","d","e"] 内部 Array firstArray中没有的对象。
1)secondArray 内部 Array secondArray中没有的对象。
3)firstArrayArray之间的常见对象的firstArray

所以输出基本上是:

1)secondArray
2)["b","c"]
3)["d","e"]

这里的主要问题是了解最有效的方法是什么。非常感谢你!

2 个答案:

答案 0 :(得分:3)

如果您的数组已排序且每个数组中的项都是唯一的,则最快的方法是仅处理每个项目一次。首先比较每个数组中的第一项;如果它们相等,则将其放入公共数组,然后转到第二个项目。如果一个项目小于另一个项目,它将进入较小项目的唯一数组,然后转到较小数组中的下一个项目。继续此过程,直到用完一个数组的项目,然后将第二个数组的其余项目放入该数组的唯一项目数组中。

var i = 0
var j = 0

let a = ["a", "b", "c"]
let b = ["a", "d", "e"]

var aUnique = [String]()
var bUnique = [String]()
var common = [String]()

while i < a.count && j < b.count {
    if a[i] == b[j] {
        common.append(a[i])
        i += 1
        j += 1
    } else if a[i] < b[j] {
        aUnique.append(a[i])
        i += 1
    } else {
        bUnique.append(b[j])
        j += 1
    }
}

if i < a.count {
    // put remaining items into aUnique
    aUnique += a[i ..< a.count]
} else if j < b.count {
    // put remaining items into bUnique
    bUnique += b[j ..< b.count]
}

print(common)  // ["a"]
print(aUnique) // ["b", "c"]
print(bUnique) // ["d", "e"]

<强>分析

  • 此算法每次通过循环将一个项目附加到其中一个数组。如果两个数组相对于彼此唯一,或者只有它们的最后一项是常见的,它将循环最多a.count + b.count - 1次。
  • 如果两个数组都相同,则只会循环a.count次。
  • 如果数组b的所有元素都大于数组a的元素,则它将仅循环a.count次。如果数组a的所有元素都大于数组b的元素,则它将仅循环b.count次。

答案 1 :(得分:2)

我将假设您的数组元素为Equatable

如果它们也是Hashable,并且如果元素的顺序对您不重要,并且如果(如您的示例中)所有元素都是唯一的,您可能需要考虑使用set algebra而不是有序的集合类型,例如Array。例如。在Swift中使用Set,您可以使用subtract(_:)subtracting(_:)变异/非方法1)和2),以及intersection(_:) / formIntersection(_:) 3 ),它们都使用O(1)(摊销)查找来比较集合之间的元素(与例如使用O(n)包含(_ :)的数组(带有Equatable元素)来查找某些元素的存在指定的元素)。

有关其他详细信息,请参阅language reference for Set以及与vadian相关联的主题:

如果每个数组中的元素不是唯一的,并且您希望保持多个元素以及元素之间的顺序,则可以使用其中一个数组的Set表示形式,同时过滤另一个数组。< / p>

,例如:

var firstArray = ["a","b","c"]
var secondArray = ["a","d","e"]

A)O(n)

let excludeElements = Set(secondArray)        // O(n)
secondArray = secondArray
    .filter { !excludeElements.contains($0) } // O(n) due to O(1) (amortized) .contains lookup

B)O(n)

let excludeElements = Set(firstArray)         // O(n)
secondArray = secondArray
    .filter { !excludeElements.contains($0) } // O(n) due to O(1) (amortized) .contains lookup

C)在O(n)中,使用firstArray中出现的顺序和重复:

let includeElements = Set(secondArray)  // O(n)
let commonElements = firstArray
    .filter(includeElements.contains)   // O(n) due to O(1) (amortized) .contains lookup

C)在O(n)中,使用secondArray中出现的顺序和重复:

let includeElements = Set(firstArray) // O(n)
let commonElements = secondArray
    .filter(includeElements.contains) // O(n) due to O(1) (amortized) .contains lookup

性能?

以上仅考虑渐近时间复杂度,并未考虑任何实际基准测试。通常,filter等功能方法比forwhile循环慢,所以如果性能成为您的应用的问题,您应该考虑,此时,执行分析以及自定义基准测试可能会在算法中出现瓶颈。

此外,如果已知您的数组已排序,则可以使用更有效的方法遍历它们并过滤掉结果。参见例如以下线程(C语言,但逻辑是重要部分):