Всем привет! На собеседованиях время от времени встречается вопрос как выравнить многоуровневый массив.
Если это простой двухуровневый массив вида [[1, 2], [3, 4]], то нам поможет стандартная функция высшего порядка flatMap().
Но что если нам нужно нужно выровнять более сложные массивы, например:
[1, [2]] -> [1, 2]
[1, [2, 3]] -> [1, 2, 3]
[1, [2, [3, [4]]]] -> [1, 2, 3, 4]
В этом случае мы можем написать свою рекурсивную функцию:
func flattFunction(array:[Any]) -> [Int] {
var flattenArray = [Int]()
for element in array {
if let element = element as? Int {
flattenArray.append(element)
} else if let element = element as? [Any] {
let result = flattFunction(array: element)
flattenArray += result
}
}
return flattenArray
}
Протестируем:
let arr1 = [1]
let arr2 = [1, 2, 3]
let arr3: [Any] = [1, [2]]
let arr4: [Any] = [1, [2, 3]]
let arr5: [Any] = [1, [2, [3, [4]]]]
func testFlattFunc() {
print(flattFunction(array: arr1))
print(flattFunction(array: arr2))
print(flattFunction(array: arr3))
print(flattFunction(array: arr4))
print(flattFunction(array: arr5))
}
testFlattFunc()
// Вывод:
// [1]
// [1, 2, 3]
// [1, 2]
// [1, 2, 3]
// [1, 2, 3, 4]
Надеюсь это небольшая заметка окажется полезной.
Комментарии (2)
pqbd
12.04.2024 10:53Рекурсивно...
Извините, первый раз пишу на Swift, но вот в чём проблема рекурсии
func flattFunction(array:[Any]) -> [Int] { var flattenArray = [Int]() for element in array { if let element = element as? Int { flattenArray.append(element) } else if let element = element as? [Any] { let result = flattFunction(array: element) flattenArray += result } } return flattenArray } func f(array:[Any]) -> [Int] { var tmp = array var r = [Int]() while (tmp.count > 0) { let item = tmp.removeFirst() if (item is [Any]) { tmp = (item as! [Any]) + tmp } else { r.append(item as! Int) } } return r } var arr = [1] as [Any] for _ in 1...30024 { let t = arr[0] arr[0] = [t] } func testFlattFunc() { print(f(array: arr)) print(flattFunction(array: arr)) } testFlattFunc()
https://www.programiz.com/swift/online-compiler/
[1] Stack dump: 0. Program arguments: /usr/bin/swift-frontend -frontend -interpret /tmp/SM1XhW2TlX.swift -disable-objc-interop -color-diagnostics -new-driver-path /usr/bin/swift-driver -empty-abi-descriptor -resource-dir /usr/lib/swift -module-name SM1XhW2TlX 1. Swift version 5.8.1 (swift-5.8.1-RELEASE) 2. Compiling with the current language version 3. While running user code "/tmp/SM1XhW2TlX.swift" Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it): /usr/bin/swift-frontend(+0x59da633)[0x5890ce947633] /usr/bin/swift-frontend(+0x59d854e)[0x5890ce94554e] /usr/bin/swift-frontend(+0x59da9ba)[0x5890ce9479ba] /lib/x86_64-linux-gnu/libc.so.6(+0x42520)[0x7cdcd491c520] /usr/lib/swift/linux/libswiftCore.so(+0x3f77e1)[0x7cdcd52897e1] /usr/lib/swift/linux/libswiftCore.so(+0x3d542d)[0x7cdcd526742d] Segmentation fault
Моя отработала, Ваша упала
Rorg
В итоге никуда flatMap не делать. Старая версия была deprecated с пометкой использовать compactMap в случаях, если при обработке closure возврат может быть optional.
И отдельно появилась новая версия flatMap, которая работает.. ну как flatMap