使用可选数组时,Swift flatMap会产生意外结果 [英] Swift flatMap gives unexpected result while using with optional array

查看:136
本文介绍了使用可选数组时,Swift flatMap会产生意外结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

We have an array of the Person objects and each object has another array of String, which is optional. We want the consolidated list of car names in our society.

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]

// Expected Result: ["i20", "Swift VXI", "Crita", "Swift VXI"]

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

// Result: [["i20", "Swift VXI"], ["Crita", "Swift VXI"]]

为什么它不给我一个字符串数组作为结果?

Why it's not giving me a single array of string as result?

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

I did couple of changes in the above code like my code as below, Instead of "nil", we tried to pass the empty array to the 3rd Person object.

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

结果是:


[[i20,Swift VXI],[Crita,Swift VXI],[]]

[["i20", "Swift VXI"], ["Crita", "Swift VXI"], []]

仍然不是预期的结果。

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

If I remove the optional from the cars Array like,

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

然后按预期工作。

结果:


[i20,Swift VXI,Crita,Swift VXI ]

["i20", "Swift VXI", "Crita", "Swift VXI"]

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

I am not sure why it's not giving the above result if the member is of type Collection is optional?

推荐答案

问题在于 map flatMap ,期权是0或1个元素的集合。您可以直接在选项上调用 map flatMap 而无需解包它们:

The issue is that for the purposes of map and flatMap, optionals are collections of 0 or 1 elements. You can directly call map and flatMap on optionals without unwrapping them:

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"

为了用更熟悉的术语说明你目前的情况,你看的是相当于:

To illustrate in more familiar terms your current situation, you're looking at the equivalent of this:

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

如果你有一个 var人:[人] 并调用 persons.flatMap {$ 0.cars} ,此操作的结果类型无疑是 [[String]] :你从三层收集开始,最后得到两个。

If you had a var persons: [Person] and called persons.flatMap { $0.cars }, the resulting type of this operation would unquestionably be [[String]]: you start out with three layers of collections and you end up with two.

这也是 [String]的实际情况?而不是 [[String]]

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

In the case that you are describing, I would advise dropping the optional and using empty arrays. I'm not sure that the distinction between a nil array and an empty array is truly necessary in your case: my interpretation is that a nil array means that the person is incapable of owning a car, whereas an empty array means that the person is capable of owning a car but doesn't have any.

如果你不能删除可选项,那么你需要两次调用 flatMap 来展平两层而不是只有一层:

If you cannot drop the optional, then you will need to call flatMap twice to flatten two layers instead of only one:

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

这篇关于使用可选数组时,Swift flatMap会产生意外结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆