将数组扩展转换为 SequenceType?
Convert Array extension to SequenceType?
我将我在我的应用程序中使用的一些常用功能放在一起,并提出了以下扩展:
public extension CollectionType {
public func toArray() -> [Self.Generator.Element] {
return self.map { [=10=] }
}
}
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
吗?
一般来说,@noescape
应该在闭包未保存以供日后使用的任何时候使用,它似乎适用于您这里的两个闭包。
你说的 "can they be applied to a lower level type" 的意思不是很清楚 或多或少,你可以为其他一些协议创建这些扩展的版本,但你现有的 skip
函数只能应用到 Array
(顺便说一句,SequenceType
上有一个现有函数 dropFirst
做完全相同的事情)
对于 take
和 skip
你可能想要实际考虑返回一个 ArraySlice
因为这避免了复制原始数组:
extension Array {
func take(count:Int) -> ArraySlice<Element> {
return self[0..<count]
}
func drop(count:Int) -> ArraySlice<Element> {
return self[count..<self.count]
}
}
请注意,对于这两个,您可能(可能)想要添加一些错误 detection/handling,因为如果 count > self.count
.
它们会爆炸
同样,使用 contains
来实现 any
和 all
可能更有效,因为它不会导致仅为计数构建新数组:
extension Array {
func any(@noescape predicate:(Element)->Bool) -> Bool {
return contains(predicate)
}
func all(@noescape predicate:(Element)->Bool) -> Bool {
return !contains { !predicate([=11=]) }
}
}
作为将其中一些定义为 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([=12=]) }
}
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)
}
}
我将我在我的应用程序中使用的一些常用功能放在一起,并提出了以下扩展:
public extension CollectionType {
public func toArray() -> [Self.Generator.Element] {
return self.map { [=10=] }
}
}
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
吗?
一般来说,@noescape
应该在闭包未保存以供日后使用的任何时候使用,它似乎适用于您这里的两个闭包。
你说的 "can they be applied to a lower level type" 的意思不是很清楚 或多或少,你可以为其他一些协议创建这些扩展的版本,但你现有的 skip
函数只能应用到 Array
(顺便说一句,SequenceType
上有一个现有函数 dropFirst
做完全相同的事情)
对于 take
和 skip
你可能想要实际考虑返回一个 ArraySlice
因为这避免了复制原始数组:
extension Array {
func take(count:Int) -> ArraySlice<Element> {
return self[0..<count]
}
func drop(count:Int) -> ArraySlice<Element> {
return self[count..<self.count]
}
}
请注意,对于这两个,您可能(可能)想要添加一些错误 detection/handling,因为如果 count > self.count
.
同样,使用 contains
来实现 any
和 all
可能更有效,因为它不会导致仅为计数构建新数组:
extension Array {
func any(@noescape predicate:(Element)->Bool) -> Bool {
return contains(predicate)
}
func all(@noescape predicate:(Element)->Bool) -> Bool {
return !contains { !predicate([=11=]) }
}
}
作为将其中一些定义为 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([=12=]) }
}
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)
}
}