Comment concaténer ou fusionner des tableaux dans Swift?

397

S'il y a deux tableaux créés dans swift comme ceci:

var a:[CGFloat] = [1, 2, 3]
var b:[CGFloat] = [4, 5, 6]

Comment peuvent-ils être fusionnés [1, 2, 3, 4, 5, 6]?

Hristo
la source
Ceci est un sous-ensemble de stackoverflow.com/q/24465281/78336
neoneye

Réponses:

691

Vous pouvez concaténer les tableaux avec +, en créant un nouveau tableau

let c = a + b
print(c) // [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]

ou ajoutez un tableau à l'autre avec +=(ou append):

a += b

// Or:
a.append(contentsOf: b)  // Swift 3
a.appendContentsOf(b)    // Swift 2
a.extend(b)              // Swift 1.2

print(a) // [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]
Martin R
la source
[AnyObect]? n'est pas identique à CGFloat. Lors de la concaténation des tableaux AnyObject.
khunshan
6
Khunshan: AnyObjectindique un objet qui, si je comprends bien, signifie quelque chose qui est instancié à partir d'un type de classe. CGFloatn'est pas un objet, c'est une valeur scalaire. Si je comprends bien, les tableaux peuvent contenir des scalaires, sauf s'ils sont définis comme contenant AnyObjectou sont affinés. Cependant, je soupçonne ici que le problème est que le tableau est enveloppé dans une option, vous devez donc le déballer avec !ou d' ?abord.
Owen Godfrey
Savons-nous si l'intelligence Copy-On-Write de Swift 2 s'étend à déterminer si la bpartie de aest modifiée (donc peut-être en éluder une copie bpendant a.appendContentsOf(b))?
Ephemera
1
@OwenGodfrey merci. j'ai peu de confusion sur appendContentsOf et insertContentsOf.
khunshan
137

Avec Swift 5, selon vos besoins, vous pouvez choisir l'une des six façons suivantes pour concaténer / fusionner deux tableaux.


#1. Fusionner deux tableaux dans un nouveau tableau avec Arrayl' +(_:_:)opérateur générique de

Arraya un +(_:_:)opérateur générique. +(_:_:)a la déclaration suivante :

Crée une nouvelle collection en concaténant les éléments d'une collection et d'une séquence.

static func + <Other>(lhs: Array<Element>, rhs: Other) -> Array<Element> where Other : Sequence, Self.Element == Other.Element

L'exemple de code Playground suivant montre comment fusionner deux tableaux de type [Int]dans un nouveau tableau à l'aide+(_:_:) un opérateur générique:

let array1 = [1, 2, 3]
let array2 = [4, 5, 6]

let flattenArray = array1 + array2
print(flattenArray) // prints [1, 2, 3, 4, 5, 6]

# 2. Ajoutez les éléments d'un tableau dans un tableau existant avecArray l' +=(_:_:)opérateur générique de

Arraya un +=(_:_:)opérateur générique.+=(_:_:)a la déclaration suivante :

Ajoute les éléments d'une séquence à une collection remplaçable par plage.

static func += <Other>(lhs: inout Array<Element>, rhs: Other) where Other : Sequence, Self.Element == Other.Element

L'exemple de code Playground suivant montre comment ajouter les éléments d'un tableau de type [Int]dans un tableau existant à l'aide de+=(_:_:) un opérateur générique:

var array1 = [1, 2, 3]
let array2 = [4, 5, 6]

array1 += array2
print(array1) // prints [1, 2, 3, 4, 5, 6]

# 3. Ajouter un tableau à un autre tableau avec Arrayla append(contentsOf:)méthode de

Swift Arraya une append(contentsOf:)méthode. append(contentsOf:)a ce qui suit déclaration :

Ajoute les éléments d'une séquence ou d'une collection à la fin de cette collection.

mutating func append<S>(contentsOf newElements: S) where S : Sequence, Self.Element == S.Element

L'exemple de code Playground suivant montre comment ajouter un tableau à un autre tableau de type à l' [Int]aide de la append(contentsOf:)méthode:

var array1 = [1, 2, 3]
let array2 = [4, 5, 6]

array1.append(contentsOf: array2)
print(array1) // prints [1, 2, 3, 4, 5, 6]

# 4. Fusionnez deux tableaux dans un nouveau tableau avecSequence la flatMap(_:)méthode de

Swift fournit une flatMap(_:)méthode pour tous les types conformes au Sequenceprotocole (y compris Array). flatMap(_:)a la déclaration suivante :

Renvoie un tableau contenant les résultats concaténés de l'appel de la transformation donnée avec chaque élément de cette séquence.

func flatMap<SegmentOfResult>(_ transform: (Self.Element) throws -> SegmentOfResult) rethrows -> [SegmentOfResult.Element] where SegmentOfResult : Sequence

L'exemple de code Playground suivant montre comment fusionner deux tableaux de type [Int]dans un nouveau tableau à l'aide de la flatMap(_:)méthode:

let array1 = [1, 2, 3]
let array2 = [4, 5, 6]

let flattenArray = [array1, array2].flatMap({ (element: [Int]) -> [Int] in
    return element
})
print(flattenArray) // prints [1, 2, 3, 4, 5, 6]

# 5. Fusionner deux tableaux dans un nouveau tableau avec Sequence'sjoined() méthode et la méthode Arraydeinit(_:) initialiseur de

Swift fournit une joined()méthode pour tous les types conformes au Sequenceprotocole (y compris Array). joined()a la déclaration suivante:

Renvoie les éléments de cette séquence de séquences, concaténés.

func joined() -> FlattenSequence<Self>

De plus, Swift Arraya un init(_:)initialiseur. init(_:)a la déclaration suivante :

Crée un tableau contenant les éléments d'une séquence.

init<S>(_ s: S) where Element == S.Element, S : Sequence

Par conséquent, l'exemple de code Playground suivant montre comment fusionner deux tableaux de type [Int]dans un nouveau tableau à l'aide de la joined()méthode et de l' init(_:)initialiseur:

let array1 = [1, 2, 3]
let array2 = [4, 5, 6]

let flattenCollection = [array1, array2].joined() // type: FlattenBidirectionalCollection<[Array<Int>]>
let flattenArray = Array(flattenCollection)
print(flattenArray) // prints [1, 2, 3, 4, 5, 6]

# 6. Fusionner deux tableaux dans un nouveau tableau avec Arrayla reduce(_:_:)méthode de

Swift Arraya une reduce(_:_:)méthode. reduce(_:_:)a ce qui suit déclaration :

Renvoie le résultat de la combinaison des éléments de la séquence à l'aide de la fermeture donnée.

func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (Result, Element) throws -> Result) rethrows -> Result

Le code Playground suivant montre comment fusionner deux tableaux de type [Int]dans un nouveau tableau à l'aide de la reduce(_:_:)méthode:

let array1 = [1, 2, 3]
let array2 = [4, 5, 6]

let flattenArray = [array1, array2].reduce([], { (result: [Int], element: [Int]) -> [Int] in
    return result + element
})
print(flattenArray) // prints [1, 2, 3, 4, 5, 6]
Imanou Petit
la source
5
merci pour le partage de ce code, bonne explication, juste pour ajouter à votre réponse, ce serait mieux, si vous dites lequel est le plus efficace par la performance?
kokemomuke
J'aime +pour 2 tableaux et joined()pour un tableau de tableaux.
Cœur
Si vous fusionnez plus de 2 tableaux (ou chaînes ou quoi que ce soit d'autre), évitez d'utiliser l' +opérateur, cela génère des temps de compilation absolument insensés.
lawicko
@lawicko quelle méthode recommanderez-vous?
CyberMew
@CyberMew Tout ce qui n'utilise pas d'opérateurs surchargés, j'aime la méthode # 3 parce que je pense qu'elle est la plus lisible, mais j'aime aussi la méthode # 4 avec la carte plate. Pour les chaînes, j'aime la méthode # 5 car à la fin, vous obtenez immédiatement la chaîne jointe.
lawicko
34

Si vous n'êtes pas un grand fan de la surcharge des opérateurs, ou tout simplement plus d'un type fonctionnel:

// use flatMap
let result = [
    ["merge", "me"], 
    ["We", "shall", "unite"],
    ["magic"]
].flatMap { $0 }
// Output: ["merge", "me", "We", "shall", "unite", "magic"]

// ... or reduce
[[1],[2],[3]].reduce([], +)
// Output: [1, 2, 3]
Mazyod
la source
22

Ma méthode préférée depuis Swift 2.0 est aplatir

var a:[CGFloat] = [1, 2, 3]
var b:[CGFloat] = [4, 5, 6]

let c = [a, b].flatten()

Cela reviendra FlattenBidirectionalCollectiondonc si vous voulez juste un CollectionTypece sera suffisant et vous aurez une évaluation paresseuse gratuitement. Si vous avez exactement besoin du tableau, vous pouvez le faire:

let c = Array([a, b].flatten())
Tomasz Bąk
la source
2
flatten()ne semble plus exister de nos jours. Mais vous pouvez envisager joined().
Cœur
13

Pour compléter la liste des alternatives possibles, reducepourrait être utilisé pour implémenter le comportement d' aplatir :

var a = ["a", "b", "c"] 
var b = ["d", "e", "f"]

let res = [a, b].reduce([],combine:+)

La meilleure alternative (performances / mémoire) parmi celles présentées est tout simplement flatten , qui enveloppe simplement les tableaux d'origine paresseusement sans créer de nouvelle structure de tableau.

Mais remarquez que Aplatir ne retourne pas unLazyCollection , de sorte que le comportement paresseux ne sera pas propagé à l'opération suivante le long de la chaîne (map, flatMap, filter, etc ...).

Si lazyness est logique dans votre cas particulier, rappelez - vous juste ou précédez ajouter un .lazyà flatten(), par exemple, modifier Tomasz exemple de cette façon:

let c = [a, b].lazy.flatten()
Umberto Raimondi
la source
Dans quelle mesure cette réponse est-elle encore valable en 2019 avec Swift 5.1?
willbattel
flatten () n'existe plus. jointe () peut être utilisée à la place d'aplatir ()
Pranav Pravakar
4

Si vous voulez que le deuxième tableau soit inséré après un index particulier, vous pouvez le faire (à partir de Swift 2.2):

let index = 1
if 0 ... a.count ~= index {
     a[index..<index] = b[0..<b.count]
}
print(a) // [1.0, 4.0, 5.0, 6.0, 2.0, 3.0] 
Vitalii
la source
4

Swift 3.0

Vous pouvez créer un nouveau tableau en ajoutant deux tableaux existants avec des types compatibles avec l'opérateur d'addition ( +). Le type du nouveau tableau est déduit du type des deux tableaux que vous ajoutez ensemble,

let arr0 = Array(repeating: 1, count: 3) // [1, 1, 1]
let arr1 = Array(repeating: 2, count: 6)//[2, 2, 2, 2, 2, 2]
let arr2 = arr0 + arr1 //[1, 1, 1, 2, 2, 2, 2, 2, 2]

ce sont les bons résultats des codes ci-dessus.

Lorem Ipsum Dolor
la source
4
var arrayOne = [1,2,3]
var arrayTwo = [4,5,6]

si vous voulez un résultat comme: [1,2,3, [4,5,6]]

arrayOne.append(arrayTwo)

le code ci-dessus convertira arrayOne en un seul élément et l'ajoutera à la fin de arrayTwo.

si vous voulez un résultat comme: [1, 2, 3, 4, 5, 6] alors,

arrayOne.append(contentsOf: arrayTwo)

le code ci-dessus ajoutera tous les éléments de arrayOne à la fin de arrayTwo.

Merci.

meMadhav
la source
4

Swift 4.X

la façon la plus simple que je connaisse est d'utiliser simplement le signe +

var Array1 = ["Item 1", "Item 2"]
var Array2 = ["Thing 1", "Thing 2"]

var Array3 = Array1 + Array2

// Array 3 will just be them combined :)
Stotch
la source
3

Voici le moyen le plus court de fusionner deux tableaux.

 var array1 = [1,2,3]
 let array2 = [4,5,6]

Les concaténer / les fusionner

array1 += array2
New value of array1 is [1,2,3,4,5,6]
handiansom
la source
1

De même, avec les dictionnaires de tableaux, on peut:

var dict1 = [String:[Int]]()
var dict2 = [String:[Int]]()
dict1["key"] = [1,2,3]
dict2["key"] = [4,5,6]
dict1["key"] = dict1["key"]! + dict2["key"]!
print(dict1["key"]!)

et vous pouvez itérer sur dict1 et ajouter dict2 si la "clé" correspond

Jeremy Andrews
la source
0

Tableau Marge de différents types de données:

var arrayInt = [Int]()
arrayInt.append(6)
var testArray = ["a",true,3,"b"] as [Any]
testArray.append(someInt)

Production :

["a", true, 3, "b", "hi", 3, [6]]
Abhishek Gupta
la source