Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flatten [Any] Array Swift

Tags:

arrays

swift

Using this Stack Overflow question I have the following code.

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

Instead of flattened being set to [1, [2, 3]] I want it to be [1, 2, 3].

What is the easiest/cleanest way to achieve this in Swift?

like image 573
Charlie Fish Avatar asked Dec 04 '22 21:12

Charlie Fish


2 Answers

There may be a better way to solve this but one solution is to write your own extension to 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())

Output:

[1, 2, 4, 5, 3, "Hi"]

This solution will handle any nesting of arrays.

like image 163
rmaddy Avatar answered Jan 01 '23 06:01

rmaddy


extension Collection where Element == Any {
    var joined: [Any] { flatMap { ($0 as? [Any])?.joined ?? [$0] } }
    func flatMapped<T>(_ type: T.Type? = nil) -> [T] { joined.compactMap { $0 as? T } }
}

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(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"]
like image 45
Leo Dabus Avatar answered Jan 01 '23 07:01

Leo Dabus