如何在知道过滤器元素是序列的情况下通过另一个Swift数组过滤Swift数组?速度很重要

时间:2018-10-04 01:49:21

标签: arrays swift

我有一个由10,000个结构组成的Swift数组:

struct Book {
    var id: Int?
    var name: String?
    var pages: Int?
    var words: Int?
}

var firstArray: [Book] = [] // contains 10,000 elements

还有第二个Swift类型为Int的Swift数组,其中包含5,000个元素:

var secondArray: [Int] = [] // contains 5,000 elements

我想通过删除firstArray中未包含id字段(Book.id)的所有元素来过滤firstArray。

知道Book.id对于firstArray中的每个元素都是唯一的,而且在序列中(从小到大)都是唯一的。例如。 1、2、3、6、8、10、14、15、16、40、50、51等(可能会跳过一些数字)

secondArray也是唯一的,并且按顺序(从小到大)

在Swift 4中筛选firstArray的最快方法是什么?

知道数组是一个序列时,随着处理数组的进行,过滤应该变得更快?这意味着如果我们在firstArray中途,我们将只遍历firstArray的一半以在secondArray中搜索匹配项。与secondArray相同,因为每次找到匹配项时数组都会变小。这一切有意义吗?

希望外面有人知道该怎么做。我已经在Android(Kotlin)上看到了此功能,但是如何在Swift中做到这一点?

我认为在Kotlin中就是这样:

firstArray?.let { dataFirstArray ->
        secondArray?.let {
            firstArray = ArrayList(dataFirstArray.asSequence().filter { dataSecondArray -> dataSecondArray in it }.toList())
        }
    }

1 个答案:

答案 0 :(得分:1)

如果id始终存在,请不要将其设为可选。

struct Book {
    var id: Int
    var name: String?
    var pages: Int?
    var words: Int?
}

最简单的过滤方法是一行:

func filter1(firstArray:[Book],secondArray:[Int]) -> [Book]
{
    return firstArray.filter{secondArray.contains($0.id)}
}

我还尝试利用以下事实对数组进行排序:

func filter2(firstArray:[Book],secondArray:[Int]) -> [Book]
{
    var j = 0;

    return firstArray.filter{
        while(j < secondArray.count && secondArray[j] < $0.id)
        {
            j += 1
        }
        if(j < secondArray.count && $0.id == secondArray[j])
        {
            j += 1
            return true
        }
        return false
    }
}

如评论所建议,我还尝试使用Set

func filter3(firstSet:Set<Book>,secondSet:Set<Int>) -> Set<Book>
{
    return firstSet.filter{secondSet.contains($0.id)}
}

使用以下代码进行了测试:

var firstArray: [Book] = (0..<10000).map{Book(id: $0, name: nil, pages: nil, words: nil)}.filter {_ in Int.random(in: 0...1) == 0}
var secondArray: [Int] = (0..<10000).filter{_ in Int.random(in: 0...1) == 0}

var timestamp = Date().timeIntervalSince1970
let result1 = filter1(firstArray: firstArray, secondArray: secondArray)
print(Date().timeIntervalSince1970 - timestamp)

timestamp = Date().timeIntervalSince1970
let result2 = filter2(firstArray: firstArray, secondArray: secondArray)
print(Date().timeIntervalSince1970 - timestamp)

timestamp = Date().timeIntervalSince1970
let result3 = filter3(firstArray: firstArray, secondSet: Set(secondArray))
print(Date().timeIntervalSince1970 - timestamp)

测试结果:

2.687404155731201
0.0014042854309082031
0.002758026123046875

希望获得帮助