如何在Swift中解包数组元素?(即Array <Int?> as Array <Int>)

Ric*_*ble 6 ios swift

让我说我有一个字符串数组,我想将它映射到一个Int数组我可以使用map函数:

var arrayOfStrings: Array = ["0", "a"]
let numbersOptional = arrayOfStrings.map { $0.toInt() }
// numbersOptional = "[Optional(0), nil]"
Run Code Online (Sandbox Code Playgroud)

Numbers现在是一个Int?数组,但我想要一个Int数组.我知道我可以这样做:

let numbers = arrayOfStrings.map { $0.toInt() }.filter { $0 != nil }.map { $0! }
// numbers = [0]
Run Code Online (Sandbox Code Playgroud)

但这似乎并不是很迅速.从Int数组转换?对于Array of Int,需要使用相当多的样板函数来调用filter和map.有更快捷的方法吗?

Jea*_*let 6

更新:从Swift 1.2开始,有一个内置的flatMap数组方法,但它不接受Optionals,所以下面的帮助程序仍然有用.


我喜欢使用辅助flatMap函数来处理这类事情,就像Scala flatMap对集合的方法一样(可以将Scala Option视为0或1元素的集合,粗略地说):

func flatMap<C : CollectionType, T>(source: C, transform: (C.Generator.Element) -> T?) -> [T] {
    var buffer = [T]()
    for elem in source {
        if let mappedElem = transform(elem) {
            buffer.append(mappedElem)
        }
    }
    return buffer
}

let a = ["0", "a", "42"]
let b0 = map(a, { $0.toInt() }) // [Int?] - [{Some 0}, nil, {Some 42}]
let b1 = flatMap(a, { $0.toInt() }) // [Int] - [0, 42]
Run Code Online (Sandbox Code Playgroud)

flatMap对于Optional更一般的flatMap应该做的事情,这个定义是一个特殊情况:

func flatMap<C : CollectionType, T : CollectionType>(source: C, transform: (C.Generator.Element) -> T) -> [T.Generator.Element] {
    var buffer = [T.Generator.Element]()
    for elem in source {
        buffer.extend(transform(elem))
    }
    return buffer
}
Run Code Online (Sandbox Code Playgroud)

我们得到的地方

let b2 = flatMap(a, { [$0, $0, $0] }) // [String] - ["0", "0", "0", "a", "a", "a", "42", "42", "42"]
Run Code Online (Sandbox Code Playgroud)


Gab*_*lla 5

使用reduce来建立新的数组可能是更地道

func filterInt(a: Array<String>) -> Array<Int> {
    return a.reduce(Array<Int>()) {
        var a = $0
        if let x = $1.toInt() {
            a.append(x)
        }
        return a
    }
}
Run Code Online (Sandbox Code Playgroud)

filterInt(["0", "a", "42"]) // [0, 42] 
Run Code Online (Sandbox Code Playgroud)

你真正想要的是一个collect(map+ filter)方法.鉴于您需要应用特定的过滤器,在这种情况下甚至flatMap可以工作(参见Jean-Philippe的回答).太糟糕了,swift标准库没有提供这两种方法.

  • 当您使用'a'作为参数名称和变量名称时,这有点令人困惑. (2认同)

Leo*_*bus 2

更新:Xcode 7.2 \xe2\x80\xa2 Swift 2.1.1

\n\n
let arrayOfStrings = ["0", "a", "1"]\nlet numbersOnly = arrayOfStrings.flatMap { Int($0) }\n\nprint(numbersOnly)   // [0,1]\n
Run Code Online (Sandbox Code Playgroud)\n