用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 是通过将原始数组中的每个元素(在本例中为整数 020)转换为结果类型的实例而获得的。例如:

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
}