Mar*_*ina 43 list-comprehension swift
语言指南没有透露列表理解的痕迹.在Swift中实现这一目标的最佳方法是什么?我正在寻找类似的东西:
evens = [ x for x in range(10) if x % 2 == 0]
Run Code Online (Sandbox Code Playgroud)
ric*_*ter 59
从Swift 2.x开始,Python样式列表理解有一些简短的等价物.
Python的公式的最直接的调整(其内容类似于"应用转换到一个序列受到过滤器")涉及的链接map
和filter
方法适用于所有SequenceType
S,并从开始Range
:
// Python: [ x for x in range(10) if x % 2 == 0 ]
let evens = (0..<10).filter { $0 % 2 == 0 }
// Another example, since the first with 'x for x' doesn't
// use the full ability of a list comprehension:
// Python: [ x*x for x in range(10) if x % 2 == 0 ]
let evenSquared = (0..<10).filter({ $0 % 2 == 0 }).map({ $0 * $0 })
Run Code Online (Sandbox Code Playgroud)
请注意,a Range
是抽象的 - 它实际上并不创建您要求它的整个值列表,只是一个懒惰地按需提供它们的构造.(在这个意义上它更像是Python xrange
.)然而,filter
调用返回一个Array
,所以你失去了"懒惰"方面.如果你想让这个集合一直保持懒惰,那么就这样说:
// Python: [ x for x in range(10) if x % 2 == 0 ]
let evens = (0..<10).lazy.filter { $0 % 2 == 0 }
// Python: [ x*x for x in range(10) if x % 2 == 0 ]
let evenSquared = (0..<10).lazy.filter({ $0 % 2 == 0 }).map({ $0 * $0 })
Run Code Online (Sandbox Code Playgroud)
与Python中的列表推导语法(以及其他一些语言中的类似构造)不同,Swift中的这些操作遵循与其他操作相同的语法.也就是说,构造,过滤和操作一系列数字的语法风格与过滤和操作对象数组一样 - 您不必使用函数/方法语法进行某种工作并列出另一个的理解语法.
你可以到通过其它功能filter
和map
通话,链其他方便的转换像sort
和reduce
:
// func isAwesome(person: Person) -> Bool
// let people: [Person]
let names = people.filter(isAwesome).sort(<).map({ $0.name })
let sum = (0..<10).reduce(0, combine: +)
Run Code Online (Sandbox Code Playgroud)
但是,根据您的目标,可能会有更简洁的方式来表达您的意思.例如,如果您特别需要偶数整数列表,则可以使用stride
:
let evenStride = 0.stride(to: 10, by: 2) // or stride(through:by:), to include 10
Run Code Online (Sandbox Code Playgroud)
与范围一样,这会让你成为一个生成器,因此你需要从中创建一个Array
或者遍历它以查看所有值:
let evensArray = Array(evenStride) // [0, 2, 4, 6, 8]
Run Code Online (Sandbox Code Playgroud)
编辑:严重修改Swift 2.x. 如果您想要Swift 1.x,请参阅编辑历史记录.
使用Swift 5,您可以选择以下七个Playground示例代码中的一个来解决您的问题.
stride(from:to:by:)
功能let sequence = stride(from: 0, to: 10, by: 2)
let evens = Array(sequence)
// let evens = sequence.map({ $0 }) // also works
print(evens) // prints [0, 2, 4, 6, 8]
Run Code Online (Sandbox Code Playgroud)
Range
filter(_:)
方法let range = 0 ..< 10
let evens = range.filter({ $0 % 2 == 0 })
print(evens) // prints [0, 2, 4, 6, 8]
Run Code Online (Sandbox Code Playgroud)
Range
compactMap(_:)
方法let range = 0 ..< 10
let evens = range.compactMap({ $0 % 2 == 0 ? $0 : nil })
print(evens) // prints [0, 2, 4, 6, 8]
Run Code Online (Sandbox Code Playgroud)
sequence(first:next:)
功能let unfoldSequence = sequence(first: 0, next: {
$0 + 2 < 10 ? $0 + 2 : nil
})
let evens = Array(unfoldSequence)
// let evens = unfoldSequence.map({ $0 }) // also works
print(evens) // prints [0, 2, 4, 6, 8]
Run Code Online (Sandbox Code Playgroud)
AnySequence
init(_:)
初始化程序let anySequence = AnySequence<Int>({ () -> AnyIterator<Int> in
var value = 0
return AnyIterator<Int> {
defer { value += 2 }
return value < 10 ? value : nil
}
})
let evens = Array(anySequence)
// let evens = anySequence.map({ $0 }) // also works
print(evens) // prints [0, 2, 4, 6, 8]
Run Code Online (Sandbox Code Playgroud)
var evens = [Int]()
for value in 0 ..< 10 where value % 2 == 0 {
evens.append(value)
}
print(evens) // prints [0, 2, 4, 6, 8]
Run Code Online (Sandbox Code Playgroud)
var evens = [Int]()
for value in 0 ..< 10 {
if value % 2 == 0 {
evens.append(value)
}
}
print(evens) // prints [0, 2, 4, 6, 8]
Run Code Online (Sandbox Code Playgroud)