用map重写for in 0...n循环
Rewite for in 0...n loop by map
我有一个 swift 代码如下
var items: [Item] = []
for i in 0...20 {
items.append( makeItem(atIndex: i) )
}
是否可以像这样重写上面的内容
var items: [Item] = [0...20].map {
makeItem(atIndex: i)
}
语法 [0...20]
是一个包含 单个闭范围 的数组 Int
, 不是 数组Int 的(这是您通常希望在 map()
上调用的内容),所以您真正想要的是:
let integers = [
0, 1, 2, 3, 4, 5,
6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16,
17 ,18, 19, 20]
integers.map{
// your code here
}
(我原来的回答漏掉了这个区别,我现在更正了。请参阅其他关于如何将范围转换为 Int
的数组的答案)
两者都将执行括号内的块 21 次,每次对应数组中的每个整数。
但与 for
循环相反,map()
函数预期 return 某种类型的数组 ,其中每个element 是通过将原始数组中的每个元素(在本例中为整数 0
到 20
)转换为结果类型的实例而获得的。例如:
let textRepresentations: [String] = integers.map {
return "\([=11=])"
}
// Now textRepresentations contains "0", "1", etc.
如果您的目标是 assemble 一个基于这 21 个整数创建的对象的数组,map()
会给您一个比您更优雅的解决方案会以更 "C-like" 的方式完成,例如:
var textRepresentations: [String] = []
for i in 0 ... 20 {
textRepresentations.append("\(i)")
}
但是如果你只需要为每个整数执行一次逻辑,结果没有数组,那么使用 map()
(并丢弃结果)会让人们看起来很尴尬和困惑维护该代码(包括你未来的自己)。
此外,for ... in
循环的 "Swifty" 替代方法是 foreach
(看起来更像 map()
,减去 returned数组):
integers.foreach {
// (use [=13=] instead of i)
}
...or, more verbosely:
integers.foreach { (element) in
// (use `element`, of course)
}
有可能,只是不要将范围包裹在数组中,所以使用 (0...20)
而不是 [0...20]
您甚至可以传递函数的名称,而不必通过一次调用创建闭包。
let items = (0...20).map(makeItem)
要获得准确的语法,您可以创建扩展:
extension Array where Element == ClosedRange<Int> {
@discardableResult
func map(_ f: @escaping(Int) -> Void) -> [Int]{
var result : [Int] = []
for i in 0 ..< self[0].count {
result.append(i)
f(i)
}
return result
}
}
并这样称呼它:
let items = [0...50].map {
print([=11=]) // current index
}
print(items)
请注意,项目将是 [Int]
,这解决了您的问题 在 您的编辑之前,当您只想编写一个 for
循环时,如下所示:
[0...50].map {
print([=12=]) // current index
}
我有一个 swift 代码如下
var items: [Item] = []
for i in 0...20 {
items.append( makeItem(atIndex: i) )
}
是否可以像这样重写上面的内容
var items: [Item] = [0...20].map {
makeItem(atIndex: i)
}
语法 [0...20]
是一个包含 单个闭范围 的数组 Int
, 不是 数组Int 的(这是您通常希望在 map()
上调用的内容),所以您真正想要的是:
let integers = [
0, 1, 2, 3, 4, 5,
6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16,
17 ,18, 19, 20]
integers.map{
// your code here
}
(我原来的回答漏掉了这个区别,我现在更正了。请参阅其他关于如何将范围转换为 Int
的数组的答案)
两者都将执行括号内的块 21 次,每次对应数组中的每个整数。
但与 for
循环相反,map()
函数预期 return 某种类型的数组 ,其中每个element 是通过将原始数组中的每个元素(在本例中为整数 0
到 20
)转换为结果类型的实例而获得的。例如:
let textRepresentations: [String] = integers.map {
return "\([=11=])"
}
// Now textRepresentations contains "0", "1", etc.
如果您的目标是 assemble 一个基于这 21 个整数创建的对象的数组,map()
会给您一个比您更优雅的解决方案会以更 "C-like" 的方式完成,例如:
var textRepresentations: [String] = []
for i in 0 ... 20 {
textRepresentations.append("\(i)")
}
但是如果你只需要为每个整数执行一次逻辑,结果没有数组,那么使用 map()
(并丢弃结果)会让人们看起来很尴尬和困惑维护该代码(包括你未来的自己)。
此外,for ... in
循环的 "Swifty" 替代方法是 foreach
(看起来更像 map()
,减去 returned数组):
integers.foreach {
// (use [=13=] instead of i)
}
...or, more verbosely:
integers.foreach { (element) in
// (use `element`, of course)
}
有可能,只是不要将范围包裹在数组中,所以使用 (0...20)
而不是 [0...20]
您甚至可以传递函数的名称,而不必通过一次调用创建闭包。
let items = (0...20).map(makeItem)
要获得准确的语法,您可以创建扩展:
extension Array where Element == ClosedRange<Int> {
@discardableResult
func map(_ f: @escaping(Int) -> Void) -> [Int]{
var result : [Int] = []
for i in 0 ..< self[0].count {
result.append(i)
f(i)
}
return result
}
}
并这样称呼它:
let items = [0...50].map {
print([=11=]) // current index
}
print(items)
请注意,项目将是 [Int]
,这解决了您的问题 在 您的编辑之前,当您只想编写一个 for
循环时,如下所示:
[0...50].map {
print([=12=]) // current index
}