将Array扩展转换为SequenceType?

时间:2016-03-16 17:48:47

标签: arrays swift swift2 swift-extensions

我正在整理我在我的应用中使用的一些常用功能,并提出了以下扩展程序:

public extension CollectionType {
    public func toArray() -> [Self.Generator.Element] {
        return self.map { $0 }
    }
}

public extension Array {

    public func any(fn: (Element) -> Bool) -> Bool {
        return self.filter(fn).count > 0
    }

    public func all(fn: (Element) -> Bool) -> Bool {
        return self.filter(fn).count == self.count
    }

    public func take(count:Int) -> [Element] {
        var to = [Element]()
        var i = 0
        while i < self.count && i < count {
            to.append(self[i++])
        }
        return to
    }

    public func skip(count:Int) -> [Element] {
        var to = [Element]()
        var i = count
        while i < self.count {
            to.append(self[i++])
        }
        return to
    }
}

它们可以应用于SequenceType等较低级别的类型吗?另外,我是否必须将@noescape置于这些功能的任何位置?

1 个答案:

答案 0 :(得分:3)

一般来说,只要没有保存闭包以供以后使用,就应该使用@noescape,这似乎适用于你在这里的两个闭包。

“你能将它们应用于较低级别的类型”并不是很清楚你的意思“或多或少显然,你可以为其他一些协议创建这些扩展的版本,但你现有的skip函数只能应用于Array(顺便说一下,dropFirst上的现有函数SequenceType执行完全相同的操作)

对于takeskip,您可能希望实际考虑返回ArraySlice,因为这样可以避免复制原始数组:

extension Array {
    func take(count:Int) -> ArraySlice<Element> {
        return self[0..<count]
    }

    func drop(count:Int) -> ArraySlice<Element> {
        return self[count..<self.count]
    }
}

请注意,对于这两者,您可能(可能)想要添加一些错误检测/处理,因为如果count > self.count它们会爆炸。

同样,使用contains实现anyall可能更有效,因为它不会导致为计数构建新数组:

extension Array {
    func any(@noescape predicate:(Element)->Bool) -> Bool {
        return contains(predicate)
    }
    func all(@noescape predicate:(Element)->Bool) -> Bool {
        return !contains { !predicate($0) }
    }
}

作为将其中一些定义为SequenceType的扩展名的示例:

extension SequenceType {
    func any(@noescape predicate:(Generator.Element)->Bool) -> Bool {
        return contains(predicate)
    }
    func all(@noescape predicate:(Generator.Element)->Bool) -> Bool {
        return !contains { !predicate($0) }
    }
    func drop(count:Int) -> Self.SubSequence {
        return self.dropFirst(count)
    }
}

并且,作为将take实现为序列扩展的示例:

struct TakeFromSequenceSequence<S:SequenceType> : SequenceType {
    var limit : Int
    var sequence : S

    func generate() -> AnyGenerator<S.Generator.Element> {
        var generator = sequence.generate()
        var limit = self.limit

        return anyGenerator {
            guard limit > 0 else {
                return nil
            }

            limit = limit - 1

            return generator.next()
        }
    }
}


extension SequenceType {
    func take(count:Int) -> TakeFromSequenceSequence<Self> {
        return TakeFromSequenceSequence(limit: count, sequence: self)
    }
}