使用可选数组

时间:2018-02-15 05:57:31

标签: ios swift flatmap

我们有一个Person对象数组,每个对象都有另一个String数组,这是可选的。 我们想要在我们的社会中整合汽车名称列表。

struct Person {
    let name: String
    let address: String
    let age: Int
    let income: Double
    let cars: [String]?
}
let personsArray = [Person(name:"Santosh", address: "Pune, India", age:34, income: 100000.0, cars:["i20","Swift VXI"]),
                   Person(name: "John", address:"New York, US", age: 23, income: 150000.0, cars:["Crita", "Swift VXI"]),
                   Person(name:"Amit", address:"Nagpure, India", age:17, income: 200000.0, cars:nil)]

let flatmapArray = personsArray.flatMap({$0.cars})
print(flatmapArray)
  

//预期结果:[" i20"," Swift VXI"," Crita"," Swift VXI"]

     

//结果:[[" i20"," Swift VXI"],[" Crita"," Swift VXI"]]

为什么它没有给我一个字符串数组?

我在上面的代码中做了几处更改,如下面的代码, 我们尝试将空数组传递给第3个Person对象,而不是" nil"。

Person(name:"Amit", address:"Nagpure, India", age:17, income: 200000.0, cars:Array())

结果是:

  

[[&#34; i20&#34;,&#34; Swift VXI&#34;],[&#34; Crita&#34;,&#34; Swift VXI&#34;],[]] < / p>

仍然不是预期的结果。

如果我从汽车数组中删除可选项,

let cars: [String]  
Person(name:"Amit", address:"Nagpure, India", age:17, income: 200000.0, cars:Array()) 

然后按预期工作。

结果:

  

[&#34; i20&#34;,&#34; Swift VXI&#34;,&#34; Crita&#34;,&#34; Swift VXI&#34;]

我不知道为什么如果成员类型为Collection是可选的,它没有给出上述结果?

3 个答案:

答案 0 :(得分:6)

问题是,出于mapflatMap的目的,选项是0或1个元素的集合。您可以直接在选项上调用mapflatMap,而无需将其解包:

let foo: Int? = 5
foo.map { $0 * $0 } // Int? = 25; "collection of one element"
let bar: Int? = nil
bar.map { $0 * $0 } // Int? = nil; "collection of zero elements"

为了更熟悉地说明您目前的情况,您需要查看相应的内容:

class Person {
    let cars: [[String]]
}

如果您有一个var persons: [Person]并且名为persons.flatMap { $0.cars },那么此操作的结果类型无疑将是[[String]]:您从三层集合开始,最后得到两个。

这也是[String]?而不是[[String]]实际发生的事情。

在您描述的情况下,我建议删除可选项并使用空数组。我不确定nil数组和empty数组之间的区别是否真的是必要的:我的解释是零数组意味着该人无法拥有一辆汽车而一个空数组意味着这个人有能力拥有一辆汽车但却没有汽车。

如果你不能删除可选项,那么你需要拨打flatMap两次才能展平两层而不只是一层:

persons.flatMap { $0.cars }.flatMap { $0 }

答案 1 :(得分:2)

为什么let cars: [String]let cars: [String]?的{​​{1}}不同?

flatMap上有两种flatMap;

1)将传递给它的闭包返回的序列变平,

2)从传递给它的闭包中过滤掉nils(注意这个重载很快将重命名为compactMap以避免混淆,因为@krunal在评论中提到)

在您的代码中,您使用的是nil过滤重载,因此过滤掉了数组中的nils。但是,它不会对嵌套数组进行任何展平。你可以再次调用flatMap来实现它。

喜欢

sequences

答案 2 :(得分:0)

对于包含Optionals的数组,您需要再次调用flatMap: personsArray.flatMap {$ 0.cars} .flatMap {$ 0}