Come posso concatenare o unire le matrici in Swift?


Risposte:


691

È possibile concatenare gli array con +, creando un nuovo array

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

oppure aggiungi un array all'altro con +=(o 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]

[AnyObect]? non è identico a CGFloat. Durante la concatenazione di array AnyObject.
Khunshan,

6
Khunshan: AnyObjectindica un oggetto, che a quanto ho capito significa qualcosa che è istanziato da un tipo di classe. CGFloatnon è un oggetto, è un valore scalare. A quanto ho capito, gli array possono contenere scalari, a meno che non sia definito come contenente AnyObjecto siano ulteriormente perfezionati. Tuttavia, sospetto che qui il problema sia che l'array è racchiuso in un optional, quindi devi scartarlo con !o ?prima.
Owen Godfrey,

Sappiamo se l'intelligenza Copy-On-Write di Swift 2 si estende al determinare se la bparte di aviene modificata (quindi è possibile che ne venga eliminata una copia bdurante a.appendContentsOf(b))?
Ephemera,

1
@OwenGodfrey grazie. ho poca confusione su appendContentsOf e insertContentsOf.
Khunshan,


137

Con Swift 5, in base alle tue esigenze, puoi scegliere uno dei sei seguenti modi per concatenare / unire due array.


# 1. Unire due array in un nuovo array con Arrayl' +(_:_:)operatore generico

Arrayha un +(_:_:)operatore generico. +(_:_:)ha la seguente dichiarazione :

Crea una nuova raccolta concatenando gli elementi di una raccolta e una sequenza.

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

Il seguente codice di esempio Playground mostra come unire due matrici di tipo [Int]in un nuovo array usando un +(_:_:)operatore generico:

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

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

# 2. Aggiungi gli elementi di un array in un array esistente con Arrayl' +=(_:_:)operatore generico

Arrayha un +=(_:_:)operatore generico. +=(_:_:)ha la seguente dichiarazione :

Aggiunge gli elementi di una sequenza a una raccolta sostituibile dall'intervallo.

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

Il seguente codice di esempio Playground mostra come aggiungere gli elementi di una matrice di tipo [Int]a una matrice esistente usando un +=(_:_:)operatore generico:

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

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

# 3. Aggiungi un array ad un altro array con Arrayil append(contentsOf:)metodo di

Swift Arrayha un append(contentsOf:)metodo. append(contentsOf:)ha la seguente dichiarazione :

Aggiunge gli elementi di una sequenza o raccolta alla fine di questa raccolta.

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

Il seguente codice di esempio Playground mostra come aggiungere un array a un altro array di tipo [Int]usando il append(contentsOf:)metodo:

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

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

# 4. Unire due array in un nuovo array con Sequenceil flatMap(_:)metodo di

Swift fornisce un flatMap(_:)metodo per tutti i tipi conformi al Sequenceprotocollo (incluso Array). flatMap(_:)ha la seguente dichiarazione :

Restituisce un array contenente i risultati concatenati di chiamata della trasformazione specificata con ciascun elemento di questa sequenza.

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

Il seguente codice di esempio Playground mostra come unire due matrici di tipo [Int]in un nuovo array usando il flatMap(_:)metodo:

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. Unire due array in un nuovo array con Sequenceil joined()metodo e Arrayl' init(_:)inizializzatore

Swift fornisce un joined()metodo per tutti i tipi conformi al Sequenceprotocollo (incluso Array). joined()ha la seguente dichiarazione :

Restituisce gli elementi di questa sequenza di sequenze, concatenati.

func joined() -> FlattenSequence<Self>

Inoltre, Swift Arrayha un init(_:)inizializzatore. init(_:)ha la seguente dichiarazione :

Crea una matrice contenente gli elementi di una sequenza.

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

Pertanto, il seguente codice di esempio Playground mostra come unire due matrici di tipo [Int]in un nuovo array usando il joined()metodo e l' init(_:)inizializzatore:

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. Unire due array in un nuovo array con Arrayil reduce(_:_:)metodo di

Swift Arrayha un reduce(_:_:)metodo. reduce(_:_:)ha la seguente dichiarazione :

Restituisce il risultato della combinazione degli elementi della sequenza usando la chiusura specificata.

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

Il seguente codice Playground mostra come unire due matrici di tipo [Int]in un nuovo array usando il reduce(_:_:)metodo:

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]

5
grazie per aver condiviso questo codice, una buona spiegazione, solo un'aggiunta alla tua risposta, sarebbe meglio se dici quale è più efficiente in termini di prestazioni?
kokemomuke,

Mi piace +per 2 array e joined()per un array di array.
Cœur

Se si stanno unendo più di 2 array (o stringhe o qualsiasi altra cosa), trattenersi dall'utilizzare l' +operatore, generando tempi di compilazione assolutamente folli.
lawicko,

@lawicko quale metodo mi consigliate?
CyberMew,

@CyberMew Qualunque cosa che non utilizza operatori sovraccaricati, mi piace il metodo n. 3 perché penso che sia più leggibile, ma mi piace anche il metodo n. 4 con la mappa piatta. Per le stringhe mi piace il metodo n. 5 perché alla fine ottieni subito la stringa unita.
lawicko,

34

Se non sei un grande fan del sovraccarico dell'operatore, o semplicemente più di un tipo funzionale:

// 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]

22

Il mio metodo preferito da Swift 2.0 è appiattito

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

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

Questo tornerà FlattenBidirectionalCollectionquindi se vuoi solo CollectionTypequesto sarà sufficiente e avrai una valutazione pigra gratuitamente. Se hai bisogno esattamente dell'array puoi farlo:

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

2
flatten()non sembra esistere più al giorno d'oggi. Ma potresti considerare joined().
Cœur

13

Per completare l'elenco di possibili alternative, reducepotrebbe essere utilizzato per implementare il comportamento di appiattire :

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

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

La migliore alternativa (prestazioni / memoria) tra quelle presentate è semplicemente flattenquella che avvolge pigramente gli array originali senza creare una nuova struttura di array.

Ma nota che l' appiattimento non restituisce a LazyCollection, quindi il comportamento pigro non verrà propagato all'operazione successiva lungo la catena (mappa, flatMap, filtro, ecc ...).

Se pigrizia ha un senso nel vostro caso particolare, basta ricordarsi di anteporre o aggiungere una .lazyper flatten(), ad esempio, la modifica del campione Tomasz in questo modo:

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

Quanto è valida questa risposta nel 2019 con Swift 5.1?
Battaglerà il

flatten () non esiste più.
join

4

Se si desidera inserire il secondo array dopo un determinato indice, è possibile farlo (da 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] 

4

Swift 3.0

È possibile creare un nuovo array aggiungendo insieme due array esistenti con tipi compatibili con l'operatore addizione ( +). Il tipo di nuovo array viene dedotto dal tipo di due array che si sommano,

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]

questo è il giusto risultato dei codici sopra.


4
var arrayOne = [1,2,3]
var arrayTwo = [4,5,6]

se vuoi il risultato come: [1,2,3, [4,5,6]]

arrayOne.append(arrayTwo)

il codice sopra convertirà arrayOne come un singolo elemento e lo aggiungerà alla fine di arrayTwo.

se vuoi il risultato come: [1, 2, 3, 4, 5, 6], allora,

arrayOne.append(contentsOf: arrayTwo)

sopra il codice aggiungerà tutti gli elementi di arrayOne alla fine di arrayTwo.

Grazie.


4

Swift 4.X

il modo più semplice che conosco è usare semplicemente il segno +

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

var Array3 = Array1 + Array2

// Array 3 will just be them combined :)

3

Ecco il modo più breve per unire due array.

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

Concatenali / uniscili

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

1

Allo stesso modo, con i dizionari di array si può:

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"]!)

e puoi iterare su dict1 e aggiungere dict2 se la "chiave" corrisponde


0

Marge array che sono diversi tipi di dati:

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

Produzione :

["a", true, 3, "b", "hi", 3, [6]]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.