arrays - 排序数组和查找更改 - Swift

标签 arrays sorting swift optimization

好的,所以我有一个不断以快速速度接收数组的流。这就是我想要做的......

如果数组相同,什么都不做。如果不同,则创建一个新数组,将 nil 作为除已更改的值之外的每个值。

示例:

传入数组1:[1,1,1,1]

传入数组2:[1,1,2,1]

我想创建:[nil, nil, 2, nil]。仅标记更改。

我做了一些有用的东西,我只是觉得它效率不高。这是最好的方法吗?

var storedArray = [Int](count: 10, repeatedValue: 0) //array for comparing

func incomingArray(data: [Int]) {
    if data == storedArray {return} //do nothing if its the same
    var tempArray = [Int?](count: 10, repeatedValue: nil) //nil array
    for index in 0...9 {
        if storedArray[index] != data[index] {
            tempArray[index] = data[index] //replace the temp array index               
            }
        }
    //send the completed tempArray to do work  ....

    storedArray = incomingArray //save the stored as the current data
    }

所以上面的代码有效。只是效率不高。对此有更好的想法吗?

谢谢

更新 1: 我在原来的帖子中弄错了。而不是诠释。它们是 UInt8。

最佳答案

如果您关心性能,首先要寻找的是隐藏循环。这是一个:

if data == storedArray {return}

这大概是为了提高效率——如果两个数组相等,就什么都不用做。但实际上,这可能会弄巧成拙。这种比较不是恒定时间——它遍历元素并比较它们。因为你以后无论如何都要遍历它们,所以这可能不会给你太多。

您可能会争辩说它节省了您分配新数组的时间,但这会引出下一个问题,即您真的需要创建一个包含所有这些 nil 值的数组吗?为什么不将不同的索引数组生成到数组中呢?这样,差异的接收者将只需要遍历差异(可能只有几个)而不是整个数组。

从处理和存储中分离出数组可能是有意义的。这是一个函数,它接受两个数组并返回一个索引数组,其中索引不同:

func differences<T: Equatable>(lhs: [T], rhs: [T]) -> [Int] {
    // indexedPairs is a sequence of (index, (left-hand val, right-hand val))
    let indexedPairs = enumerate(zip(lhs,rhs))
    // the lazy may or may not help here, benchmark to find out...
    return lazy(indexedPairs).filter { (index, pair) in
        // only return different pairs
        pair.0 != pair.1
    }.map {
        // only return the index not the values
        $0.0
    }.array
}

注意这是一个纯函数——也就是说,它接受输入并产生结果而不引用任何外部状态。这使得作为独立函数进行测试和调试变得更加容易。

然后您可以根据它重写您的原始函数:

func incomingArray(data: [Int]) {
    let diffs = differences(storedArray, data)
    if !diffs.isEmpty {
        // send new data and diff indices for further processing
        // then overwrite the old array
        storedArray = data
    }
}

更新

基准测试表明,与简单的循环相比,过滤器/映射版本的性能非常糟糕,因此这是一个仅使用 for...indifferences 版本:

func differences<T: Equatable>(lhs: [T], rhs: [T]) -> [Int] {
    var diffs: [Int] = []
    // still using zip, since this guards against the two
    // arrays being of different sizes - doesn’t seem to
    // impact performance
    for (i,(l,r)) in zip(indices(lhs),zip(lhs,rhs)) {
        if l != r { diffs.append(i) }
    }

    return diffs
}

一些快速测试表明,如果输入很大且差异的数量很小,此版本会获得显着的加速,但如果数组大部分不同,则执行相同。

关于arrays - 排序数组和查找更改 - Swift,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28775701/

相关文章:

ios - AVFoundation - 音乐 iOS

java - paintComponent 每次我想要它时都不会被调用

ios - 如何在完成处理程序中传递数据

arrays - 计算矩阵每一行中的非零元素

java - 排序数组不同值总和到目标

c - 传递一个数组作为参数

php - 我应该将哪个 session 库与 CodeIgniter 一起使用?

arrays - 如何在vba中对数组中的日期进行排序?

python - 如何在numpy数组的给定行中保留N个最小元素?

ios - 没有从 instamojo API 获得值(value)