当其中一个元素在swift中转换失败时中止转换

当其中一个元素在swift中转换失败时中止转换,swift,Swift,在swift中,我们为数组提供了高阶函数,如map、filter、reduce等 但是如果我有一个数组,比如[Any]=[1,2,3,“1”] 我想把这个数组转换成Int数组,但是因为数组中有“1”,我的逻辑是接受整个数组无效,我会把它映射到一个空数组,比方说 在这种情况下,如何使用更高的函数 过滤很容易 let array: [Any] = [1, 2, 3, "1"] let filtered = array.compactMap{ $0 as? Int} /// prints [1, 2,

在swift中,我们为数组提供了高阶函数,如map、filter、reduce等

但是如果我有一个数组,比如[Any]=[1,2,3,“1”]

我想把这个数组转换成Int数组,但是因为数组中有“1”,我的逻辑是接受整个数组无效,我会把它映射到一个空数组,比方说

在这种情况下,如何使用更高的函数

过滤很容易

let array: [Any] = [1, 2, 3, "1"]
let filtered = array.compactMap{ $0 as? Int}
/// prints [1, 2, 3]
但我希望最终结果是[],而不是[1,2,3]

如何使用高阶函数实现这一点

压缩映射

返回一个数组,其中包含使用此序列的每个元素调用给定转换的非nil结果

因此,使用
compactMap

let array: [Any] = [1, 2, 3, "1"]


for case let element in array {
    if let _ = element as? Int {
        continue
    } else {
        print("\(element) isn't an Int, so array is invalid")
        break
    }
}

假设
数组为?[Int]??[]
不适用(例如,您需要应用更复杂的转换),您可以
抛出一个错误

enum ConversionError: Error {
    case notAllValuesWereInts
}

func convertOrThrow(_ input: Any) throws -> Int {
    switch input {
        case let int as Int: return int
        default: throw ConversionError.notAllValuesWereInts
    }
}

let array: [Any] = [1, 2, 3, "1"]
let ints: [Int]
do {
    ints = try array.map(convertOrThrow)
} catch {
    ints = []
}
print(ints)
在这种情况下,
错误
用于控制流,不携带任何有用的信息,您可以使用
try?
来简化操作:

let array: [Any] = [1, 2, 3, "1"]
let ints = (try? array.map(convertOrThrow)) ?? []

虽然这应该可以做到,因为您只想检查数组是否是整数数组

array as? [Int] ?? []
但如果您不想使用上面的代码,您可能会对以下代码感兴趣

let filtered = array.filter{($0.self as? Int) == nil}.count == 0 ? array as! [Int] : []

如果有任何元素不是
Int

数组,则上述代码生成
[]
?[Int]??[]
没有优雅的方法可以做到这一点。不能在高阶函数中使用break,continue。@dan-Yup,但需要进行一些转换。我知道我举了一个非常平凡的例子。但是假设它们都是[Int],但是我想把它们转换成一个元素小于100的有效数组。如果任何元素未能通过此转换,我应该返回一个空数组,而不是一个经过筛选的数组one@ShreeramBhat您可以
throw
@Alexander再次使用try-catch进行投掷和处理这对于此类工作来说是一种优雅的方式吗?。最好使用for循环。