变异数组扩展与inout函数

时间:2018-04-24 02:16:56

标签: swift

给定一组Color个对象,我希望能够根据条件将某种颜色提升到数组的顶部。假设每个Color都有一个布尔isBright属性,并且用于提升颜色的测试将是$0.isBright。我想宣传第一种这样的颜色。

我想提供一种更通用的方法来根据不同的测试来促进颜色。我已经通过两种方法成功完成了这项工作,但我不确定哪种更好。如果我不正确地命名或描述这些技术,请原谅我。

选项A - 输入功能

private func promoteColor(from colors: inout [Color], where promote: ((Color) -> Bool)) {
    if let index = colors.index(where: promote) {
        let color = colors.remove(at: index)
        colors.insert(color, at: 0)
    }
}

// call site:
promoteColor(from: &colors, where: { $0.isBright })

选项B - 变异阵列扩展

extension Array where Element: Color {
    mutating func promote(where promote: (Color) -> Bool) {
        if let index = index(where: promote) {
            let color = remove(at: index)
            insert(color, at: 0)
        }
    }
}

// call site:
colors.promote(where: { $0.isBright })

我更喜欢选项B的可读性,但我不确定在决定使用哪一个时我应该考虑什么。两者都有任何优点或缺点吗?

修改

我认为选项B可以推广:

extension Array {
    mutating func promote(where promote: (Element) -> Bool) {
        if let index = index(where: promote) {
            let element = remove(at: index)
            insert(element, at: 0)
        }
    }
}

1 个答案:

答案 0 :(得分:3)

在可能的情况下应该避免使用

inout,尤其是当您有变异函数时。

你最好的选择可能就是:

extension Array {
    mutating func promote(where predicate: (Element) -> Bool) {
        if let index = index(where: predicate) {
            let element = remove(at: index)
            insert(element, at: 0)
        }
    }
}

这是我昨晚想到的另一个小更新。如果你想要更多的表现。

第二个版本将避免在提升元素之后额外移动元素。我还测试了升级元素是第一个元素的地方,这个逻辑是安全的。

extension Array {
    mutating func promote(where predicate: (Element) -> Bool) {
        if let index = index(where: predicate) {
            withUnsafeMutableBufferPointer { (bufferPointer: inout UnsafeMutableBufferPointer<Element>) -> Void in
                let promotedElement = bufferPointer[index]
                for i in (0..<index).reversed() {
                    bufferPointer[i + 1] = bufferPointer[i]
                }
                bufferPointer[0] = promotedElement
            }
        }
    }
}