在2个数组中获取常用元素列表的性能

时间:2018-07-21 17:21:59

标签: swift

我有两个自定义对象数组,分别具有id和sum。 像这样:

let oldStakes = [Stake(id: 1, sum: 100), Stake(id: 2, sum: 120)]
let newStakes = [Stake(id: 5, sum: 600), Stake(id: 1, sum: 432)]

我需要获取具有相同ID的两个对象数组。 如果我愿意这样:

    newStakes = newStakes.filter{stake in oldStakes.contains{$0.id == stake.id}}.sorted{$0.id ?? 0 < $1.id ?? 0}
    oldStakes = oldStakes.filter{stake in oldStakes.contains{$0.id == stake.id}}.sorted{$0.id ?? 0 < $1.id ?? 0}

此代码的执行时间约为2秒。 如何减少执行时间?谢谢!

2 个答案:

答案 0 :(得分:0)

通常,在Set中进行搜索是O(1)操作,并且在大多数情况下会更快。

var oldStakes = [Stake(id: 1, sum: 100), Stake(id: 2, sum: 120)]
var newStakes = [Stake(id: 5, sum: 600), Stake(id: 1, sum: 432)]
let oldIds = Set(oldStakes.lazy.map{$0.id ?? 0})
let newIds = Set(newStakes.lazy.map{$0.id ?? 0})
newStakes = newStakes.filter{oldIds.contains($0.id ?? 0)}.sorted{$0.id ?? 0 < $1.id ?? 0}
oldStakes = oldStakes.filter{newIds.contains($0.id ?? 0)}.sorted{$0.id ?? 0 < $1.id ?? 0}

但是我想知道您是否真的需要在id中将Stake设置为可选。

答案 1 :(得分:0)

正如其他人所说,数组的contains(_:)函数很慢。 (每项检查的性能为O(n)。)O(1)的性能大约为contains(_:)

如果遍历一个数组并对每个元素进行contains()检查,结果将是O(n²)性能,这确实很糟糕。

OOPer向您展示了如何使用Set对象重构代码以测试成员资格。您可能还想找出一种方法,使每次都不对结果进行排序。