【问题标题】:Convert Array extension to SequenceType?将数组扩展名转换为 SequenceType?
【发布时间】:2016-03-16 17:48:46
【问题描述】:

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

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 放在这些函数的任何位置吗?

【问题讨论】:

    标签: arrays swift swift2 swift-extensions


    【解决方案1】:

    一般来说,@noescape 应该在没有保存闭包供以后使用的任何时候使用,它似乎适用于您这里的两个闭包。

    不清楚你所说的“它们可以应用于较低级别的类型”是什么意思 或多或少很明显,你可以为其他一些协议创建这些扩展的版本,但你现有的 skip 函数只能应用于Array(顺便说一句,SequenceType 上有一个现有的函数dropFirst 做同样的事情)

    对于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 &gt; 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)
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2022-01-22
      • 1970-01-01
      • 2016-07-22
      • 2022-11-15
      • 2017-12-30
      • 2022-08-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多