拼合[Any] Array Swift

Cha*_*ish 3 arrays swift

使用这个堆栈溢出问题,我有以下代码。

let numbers = [1,[2,3]] as [Any]
var flattened = numbers.flatMap { $0 }
print(flattened) // [1, [2, 3]]
Run Code Online (Sandbox Code Playgroud)

取而代之的扁平设定为[1, [2, 3]]我希望它是[1, 2, 3]

在Swift中最简单/最干净的方法是什么?

Leo*_*bus 5

extension Collection {
    func joined() -> [Any] {
        return flatMap { ($0 as? [Any])?.joined() ?? [$0] }
    }
    func flatMapped<T>(with type: T.Type? = nil) -> [T] {
        return joined().compactMap { $0 as? T }
    }
}
Run Code Online (Sandbox Code Playgroud)
let objects: [Any] = [1,[2,3],"a",["b",["c","d"]]]
let joined = objects.joined()   // [1, 2, 3, "a", "b", "c", "d"]

let integers = objects.flatMapped(with: Int.self)  // [1, 2, 3]
// setting the type explicitly
let integers2: [Int] = objects.flatMapped()        // [1, 2, 3]
// or casting
let strings = objects.flatMapped() as [String]     // ["a", "b", "c", "d"]
Run Code Online (Sandbox Code Playgroud)

  • 注意,在两种情况下,`lazy`都是多余的,因为您使用的是返回数组的重载(即,急切地求值)。您可以将`($ 0是T?[$ 0 as!T]:[])改写为`($ 0 as?T).map {[$ 0]}?[]`,尽管我个人可能会使用`switch`(例如https://gist.github.com/hamishknight/eca9b0be62056284ec37c3d49dd7db65)。另外,就我个人而言,我将使它成为“ flatten”方法,因为它不是O(1); 虽然我知道您喜欢您的计算属性:) (2认同)

rma*_*ddy 5

可能有更好的方法来解决这个问题,但一种解决方案是编写您自己的 Array 扩展:

extension Array {
    func anyFlatten() -> [Any] {
        var res = [Any]()
        for val in self {
            if let arr = val as? [Any] {
                res.append(contentsOf: arr.anyFlatten())
            } else {
                res.append(val)
            }
        }

        return res
    }
}

let numbers = [1,[2, [4, 5] ,3], "Hi"] as [Any]
print(numbers.anyFlatten())
Run Code Online (Sandbox Code Playgroud)

输出:

[1, 2, 4, 5, 3, “嗨”]

此解决方案将处理任何数组嵌套。

  • 如果我正确理解了你的测试方法,我认为这是完全错误的。您的代码的 `return` 出现在每次递归调用的末尾。你的 `return` 语句被调用的次数等于所有子数组的深度总和。在我的代码中,`return` 具有代码中 `.append(contentsOf:)` 和 `append(_:)` 调用的效果。展平 `Array(0..&lt;10)`(10 个元素,所有深度为 1)会为我调用 `return` 10 次(10 个元素),并且为你调用一次(最大深度为 1),但计数测量完全不同事物 (2认同)

Ale*_*ica 5

这是 @rmaddy 的替代实现anyFlatten

它可以最简洁地写成这样,但它相当神秘:

extension Array {
    func anyFlatten() -> [Any] {
        return self.flatMap{ ($0 as? [Any]).map{ $0.anyFlatten() } ?? [$0] }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是一个更合理的实现:

extension Array {
    func anyFlatten() -> [Any] {
        return self.flatMap{ element -> [Any] in
            if let elementAsArray = element as? [Any] { return elementAsArray.anyFlatten() }
            else { return [element] }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)