Swift flatMap gives unexpected result while using with optional array

后端 未结 3 958
半阙折子戏
半阙折子戏 2021-02-03 12:58

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.



        
3条回答
  •  栀梦
    栀梦 (楼主)
    2021-02-03 13:12

    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]]
    }
    

    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.

    This is also effectively what is happening with [String]? instead of [[String]].

    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.

    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 }
    

提交回复
热议问题