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,
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 }
}
}
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"]
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.
Here's an alternate implementation of @rmaddy's anyFlatten
:
It can be most concisely written like so, but it's quite cryptic:
extension Array {
func anyFlatten() -> [Any] {
return self.flatMap{ ($0 as? [Any]).map{ $0.anyFlatten() } ?? [$0] }
}
}
Here's a more reasonable implementation:
extension Array {
func anyFlatten() -> [Any] {
return self.flatMap{ element -> [Any] in
if let elementAsArray = element as? [Any] { return elementAsArray.anyFlatten() }
else { return [element] }
}
}
}