如何组合两个可选的数组

时间:2015-10-21 17:56:15

标签: ios arrays swift functional-programming

在组合两个可选的数组时遇到一些麻烦。不是包含可选项的数组。

let a : [String]? = ["foo"]
let b : [String]? = nil

let a : [String]? = nil
let b : [String]? = nil

let a : [String]? = ["foo"]
let b : [String]? = ["bar"]

这显然不起作用,因为数组是可选的

let combinedArrays : [String]? = a + b

使用功能性或其他更清晰的方法组合数组a和b,是否有比传统if let方法更简洁的方法?

更新 上面的例子是设计的,但下面是我试图做的更真实的例子:

func pinToAllSidesOfSuperView() -> [NSLayoutConstraint]?
{
    let horizontalConstraints : [NSLayoutConstraint]? = pinViewToLefAndRight()
    let verticalConstraints : [NSLayoutConstraint]? = pinViewToTopAndBottom()
    return horizontalConstraints + verticalConstraints
}

返回一个可选的返回值vs一个空数组会很好,所以该方法的调用者仍然可以使用可选功能(即if letguard等)与简单检查if { {1}}。

6 个答案:

答案 0 :(得分:8)

我不确定这是否足够整洁,但无论如何它会给出组合的字符串数组

var combined = (a ?? []) + (b ?? [])

许多其他选项之一是使其成为计算属性,如果组合数组为空,则返回nil

var combined:[String]?{
    let c = (a ?? []) + (b ?? [])
    return c.isEmpty ? nil : c
} 

答案 1 :(得分:6)

我会这样做:

func +<T>(lhs: Array<T>?, rhs: Array<T>?) -> Array<T>? {
    switch (lhs, rhs) {

    case (nil, nil):
        return nil

    case (nil, _):
        return rhs

    case (_, nil):
        return lhs

    default:
        return lhs! + rhs!

    }
}

let foo: [Int]? = nil
let bar: [Int]? = [1]

foo + foo   // -> nil
foo + bar   // -> [1]
bar + foo   // -> [1]
bar + bar   // -> [1, 1]

答案 2 :(得分:4)

而不是nil只是让它们成为空数组?

答案 3 :(得分:1)

采取以下解决方案之一:

1)有点难看

let a : [String]? = ["foo"]
let b : [String]? = ["bar"]
let c = (a != nil ? a! : []) + (b != nil ? b! : []) // ["foo", "bar"]

2)重新加载[String]?

的+运算符
func +(a: [String]?, b: [String]?) -> [String] {
    var s1 = a != nil ? a! : []
    let s2 = b != nil ? b! : []
    for n in s2 {
        s1.append(n)
    }
    return s1
}

let a : [String]? = ["foo"]
let b : [String]? = ["bar"]
let c : [String]? = nil
let result1 = a + b // ["foo", "bar"]
let result2 = a + c // ["foo"]

顺便说一句!在覆盖运算符中,您无法编写类似:

的内容
func +(a: [String]?, b: [String]?) -> [String] {
    return (a != nil ? a! : []) + (b != nil ? b! : [])
}

如您所见,它将导致无限递归,因此我使用了循环和append()

答案 4 :(得分:1)

对于更实用的方法,您可以为此使用compactMapflatMap

类似以下内容:

let a : [String]? = ["foo"]
let b : [String]? = ["bar"]

let combined = [a, b]   // create array with both optional arrays
    .compactMap({ $0 }) // remove optional from it
    .flatMap({ $0 })    // merge elements into a final array

希望有帮助!

答案 5 :(得分:0)

Ben的answer是正确的,也可以应用于更复杂的情况:

let arr1: [CGFloat?] = [3, 2, nil]
let arr2: [CGFloat?]? = [4, 5, nil]

let allValues: [CGFloat] = [
    arr1.compactMap({ $0 }),
    arr2?.compactMap ({ $0 })
    ]
.compactMap({ $0 })
.flatMap({ $0 })

print(allValues) // [3.0, 2.0, 4.0, 5.0]