Existe-t-il une contrepartie dans Swift to flatten
dans Scala, Xtend, Groovy, Ruby et autres
var aofa = [[1,2,3],[4],[5,6,7,8,9]]
aofa.flatten() // shall deliver [1,2,3,4,5,6,7,8,9]
bien sûr, je pourrais utiliser réduire pour cela, mais ça craint un peu
var flattened = aofa.reduce(Int[]()){
a,i in var b : Int[] = a
b.extend(i)
return b
}
Swift 3.0
reduce
:
let numbers = [[1,2,3],[4],[5,6,7,8,9]]
let reduced = numbers.reduce([], +)
flatMap
:
let numbers = [[1,2,3],[4],[5,6,7,8,9]]
let flattened = numbers.flatMap { $0 }
joined
:
let numbers = [[1,2,3],[4],[5,6,7,8,9]]
let joined = Array(numbers.joined())
Dans la bibliothèque standard Swift, la fonction joined
est implémentée pour tous les types conformes au protocole Sequence
(ou flatten
sur SequenceType
avant Swift 3), qui inclut Array
:
let numbers = [[1,2,3],[4],[5,6,7,8,9]]
let flattened = Array(numbers.joined())
Dans certains cas, l’utilisation de joined()
peut être utile car elle renvoie une collection paresseuse au lieu d’un nouveau tableau, mais elle peut toujours être convertie en tableau lorsqu'elle est transmise à Array()
initialiser comme dans l'exemple ci-dessus.
Swift 4.x
Juste pour ajouter un peu plus de complexité dans le tableau, s'il existe un tableau contenant un tableau de tableaux, alors flatMap
échouera.
Supposons que le tableau est
var array:[Any] = [1,2,[[3,4],[5,6,[7]]],8]
Ce que flatMap
ou compactMap
renvoie est:
array.compactMap({$0})
//Output
[1, 2, [[3, 4], [5, 6, [7]]], 8]
Afin de résoudre ce problème, nous pouvons utiliser notre solution simple pour la logique de boucle + récursivité
func flattenedArray(array:[Any]) -> [Int] {
var myArray = [Int]()
for element in array {
if let element = element as? Int {
myArray.append(element)
}
if let element = element as? [Any] {
let result = flattenedArray(array: element)
for i in result {
myArray.append(i)
}
}
}
return myArray
}
Alors appelez cette fonction avec le tableau donné
flattenedArray(array: array)
Le résultat est:
[1, 2, 3, 4, 5, 6, 7, 8]
Cette fonction aidera à aplatir tout type de tableau, en considérant le cas de Int
ici
Cela a fonctionné pour moi:
let numbers = [[1, 2, 3], [4, 5, 6]]
let flattenNumbers = numbers.reduce([], combine: +)
Une autre implémentation plus générique de reduce
,
let numbers = [[1,2,3],[4],[5,6,7,8,9]]
let reduced = reduce(numbers,[],+)
Ceci accomplit la même chose mais peut donner plus de perspicacité dans ce qui se passe dans reduce
.
D'après la documentation d'Apple,
func reduce<S : SequenceType, U>(sequence: S, initial: U, combine: (U, S.Generator.Element) -> U) -> U
La description
Renvoie le résultat de l'appel répété combine avec une valeur cumulée initialisée à initial et à chaque élément de sequence, à son tour.
Swift 4.x
Cette utilisation de flatMap
n'est pas obsolète et est faite pour cela . https://developer.Apple.com/documentation/Swift/sequence/2905332-flatmap
var aofa = [[1,2,3],[4],[5,6,7,8,9]]
aofa.flatMap { $0 } //[1,2,3,4,5,6,7,8,9]
Swift 4.2
J'ai écrit une extension de tableau simple ci-dessous. Vous pouvez utiliser pour aplatir un tableau contenant un autre tableau ou élément. contrairement à la méthode join ().
public extension Array {
public func flatten() -> [Element] {
return Array.flatten(0, self)
}
public static func flatten<Element>(_ index: Int, _ toFlat: [Element]) -> [Element] {
guard index < toFlat.count else { return [] }
var flatten: [Element] = []
if let itemArr = toFlat[index] as? [Element] {
flatten = flatten + itemArr.flatten()
} else {
flatten.append(toFlat[index])
}
return flatten + Array.flatten(index + 1, toFlat)
}
}
usage:
let numbers: [Any] = [1, [2, "3"], 4, ["5", 6, 7], "8", [9, 10]]
numbers.flatten()
Vous pouvez aplatir un tableau imbriqué en utilisant la méthode suivante:
var arrays = [1, 2, 3, 4, 5, [12, 22, 32], [[1, 2, 3], 1, 3, 4, [[[777, 888, 8999]]]]] as [Any]
func flatten(_ array: [Any]) -> [Any] {
return array.reduce([Any]()) { result, current in
switch current {
case(let arrayOfAny as [Any]):
return result + flatten(arrayOfAny)
default:
return result + [current]
}
}
}
let result = flatten(arrays)
print(result)
/// [1, 2, 3, 4, 5, 12, 22, 32, 1, 2, 3, 1, 3, 4, 777, 888, 8999]