web-dev-qa-db-fra.com

Aplatir un tableau de tableaux dans Swift

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
}
91
Christian Dietrich

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())
308
andreschneider

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.

25
Max Desiatov

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

Sortie du terrain de jeu: enter image description here

6
Rajan Maheshwari

Cela a fonctionné pour moi:

let numbers = [[1, 2, 3], [4, 5, 6]]
let flattenNumbers = numbers.reduce([], combine: +)
3
Rudolf Adamkovič

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.

2
Jim Hillhouse

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] 
1
NikLoy

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()
1
RahmiBozdag

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]
0
Melvin John