确定地图输出的类型

时间:2017-06-28 14:33:07

标签: swift

我正在尝试确定.map输出的类型在哪里:

func position(rows: Int, cols: Int) -> [Position] {
    return (0 ..< rows)
        .map {
            zip(
                [Int](repeating: $0, count: cols) ,
                0 ..< cols
            )
        }
}

我知道zip返回一个Zip2Sequence实例,在这种情况下是元组对(整数数组,可数整数范围)。

我得到的地图改变了序列中的元素,但我认为它需要多个参数,如val in val * 2,这里zip是唯一的参数......所以它只是将zip的输出添加到数组中? / p>

2 个答案:

答案 0 :(得分:1)

map的结果属于Array<Zip2Sequence<Array<Int>, CountableRange<Int>>>类型,基本上是[[(Int, Int)]]

我通过将map的结果分配到let result并打印print(type(of: result))来找到这一点。

map将原始序列(0 ..< rows)转换为具有rows项的数组。 zip的每个元素将依次调用(0 ..< rows),由$0表示。

如果您使用zip打包Array()来将zip序列转换为可以轻松检查的实际数组,那将会更有用:

示例:

let rows = 2
let cols = 3

let result = (0 ..< rows)
    .map { val in
        Array(zip(
            [Int](repeating: val, count: cols) ,
            0 ..< cols
        ))
}

print(result)
// [[(0, 0), (0, 1), (0, 2)], [(1, 0), (1, 1), (1, 2)]]

答案 1 :(得分:1)

(0 ..< rows)的类型为CountableRange<Int>

  1> (0 ..< 10)
$R0: (CountableRange<Int>) = {
  lowerBound = 0
  upperBound = 10
}

CountableRange符合Sequence,因此它有map方法。这个map方法接受一个参数,一个闭包。

闭包是一种功能。通常,函数具有零个或多个参数以及一个返回值。对于CountableRange<Int>.map,闭包需要采用类型为Int的一个参数,并且可以返回任何类型。

有几种方法可以在Swift中编写闭包。您的示例使用的最短路径是在{ ... }内编写单个表达式。以下是The Swift Programming Language (Swift 4)所说的内容:

  

单表达式闭包的隐式返回

     

单表达式闭包可以通过从声明中省略return关键字来隐式返回单个表达式的结果[...]

此外,如果闭包采用参数,闭包可以使用简写名称($0$1等)引用它们。而不是给它们显式名称(例如val in ...)。再次出书:

  

速记参数名称

     

Swift自动为内联闭包提供简写参数名称,可用于通过名称$0$1$2等来引用闭包参数的值。

     

如果在闭包表达式中使用这些简写参数名称,则可以从其定义中省略闭包的参数列表,并且将从期望的函数类型推断出简写参数名称的数量和类型。 in关键字也可以省略,因为闭包表达式完全由它的主体组成[...]

查看map方法调用,我们可以看到它的闭包包含一个带有隐式返回的表达式(对zip的调用),它使用$0来引用它单一论点。

zip函数有两个参数,每个参数必须是Sequencezip函数返回Zip2Sequence。在您的示例中,zip的第一个参数是[Int](repeating: $0, count: cols),其类型为[Int](或Array<Int>)。 zip的第二个参数是0 ..< cols,这是另一个CountableRange<Int>。因此,此zip调用返回的类型为Zip2Sequence<[Int], CountableRange<Int>>,这是一种有点不可思议的类型,可生成元组(Int, Int)

map返回的类型是Array,包含其closure参数返回的值。因此,在这种情况下map返回的类型为[Zip2Sequence<[Int], CountableRange<Int>>]

如果你想要更具灵活性的东西,你可以将调用包裹在zip构造函数中的Array

func position(rows: Int, cols: Int) -> [[(Int, Int)]] {
    return (0 ..< rows)
        .map {
            Array(zip(
                [Int](repeating: $0, count: cols) ,
                0 ..< cols
            ))
        }
}

Array构造函数接受任何Sequence并将其转换为Array。因此,Zip2Sequence<[Int], CountableRange<Int>>变为[(Int, Int)]map生成Array,其元素属于该类型,从而生成一对Int对的数组,或[[(Int, Int)]]