¿Cómo concatenar o fusionar matrices en Swift?


Respuestas:


691

Puede concatenar las matrices con +, creando una nueva matriz

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

o agregue una matriz a la otra 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]? no es idéntico a CGFloat. Mientras se concatena a las matrices de AnyObject.
Khunshan

66
Khunshan: AnyObjectindica un objeto, que, según tengo entendido, significa algo que se instancia a partir de un tipo de clase. CGFloatno es un objeto, es un valor escalar. Según tengo entendido, las matrices pueden contener escalares, a menos que se defina como conteniendo AnyObjecto se refinen aún más. Sin embargo, sospecho que aquí el problema es que la matriz está envuelta en una opción, por lo que debe desenvolverla con !o ?primero.
Owen Godfrey

¿Sabemos si la inteligencia Copy-On-Write de Swift 2 se extiende para determinar si la bparte de ase modifica (por lo tanto, posiblemente eludiendo una copia de bdurante a.appendContentsOf(b))?
Ephemera

1
@OwenGodfrey gracias. Tengo poca confusión sobre appendContentsOf e insertContentsOf.
Khunshan


137

Con Swift 5, de acuerdo con sus necesidades, puede elegir una de las seis formas siguientes para concatenar / fusionar dos matrices.


# 1 Combine dos matrices en una nueva matriz con Arrayel +(_:_:)operador genérico

Arraytiene un +(_:_:)operador genérico +(_:_:)tiene la siguiente declaración :

Crea una nueva colección concatenando los elementos de una colección y una secuencia.

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

El siguiente código de muestra de Playground muestra cómo fusionar dos matrices de tipo [Int]en una nueva matriz utilizando +(_:_:)un operador genérico:

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

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

# 2 Agregue los elementos de una matriz a una matriz existente con Arrayel +=(_:_:)operador genérico

Arraytiene un +=(_:_:)operador genérico +=(_:_:)tiene la siguiente declaración :

Agrega los elementos de una secuencia a una colección reemplazable por rango.

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

El siguiente código de muestra de Playground muestra cómo agregar los elementos de una matriz de tipo [Int]a una matriz existente utilizando +=(_:_:)un operador genérico:

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

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

# 3 Agregue una matriz a otra matriz con Arrayel append(contentsOf:)método de

Swift Arraytiene un append(contentsOf:)método. append(contentsOf:)tiene la siguiente declaración :

Agrega los elementos de una secuencia o colección al final de esta colección.

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

El siguiente código de muestra de Playground muestra cómo agregar una matriz a otra matriz de tipo [Int]mediante el append(contentsOf:)método:

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

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

# 4. Combine dos matrices en una nueva matriz con Sequenceel flatMap(_:)método de

Swift proporciona un flatMap(_:)método para todos los tipos que se ajustan al Sequenceprotocolo (incluido Array). flatMap(_:)tiene la siguiente declaración :

Devuelve una matriz que contiene los resultados concatenados de llamar a la transformación dada con cada elemento de esta secuencia.

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

El siguiente código de muestra de Playground muestra cómo fusionar dos matrices de tipos [Int]en una nueva matriz utilizando el flatMap(_:)método:

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. Combine dos matrices en una nueva matriz con Sequenceel joined()método y Arrayel init(_:)inicializador

Swift proporciona un joined()método para todos los tipos que se ajustan al Sequenceprotocolo (incluido Array). joined()tiene la siguiente declaración :

Devuelve los elementos de esta secuencia de secuencias, concatenados.

func joined() -> FlattenSequence<Self>

Además, Swift Arraytiene un init(_:)inicializador. init(_:)tiene la siguiente declaración :

Crea una matriz que contiene los elementos de una secuencia.

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

Por lo tanto, el siguiente código de muestra de Playground muestra cómo fusionar dos matrices de tipos [Int]en una nueva matriz utilizando el joined()método y el init(_:)inicializador:

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. Combine dos matrices en una nueva matriz con Arrayel reduce(_:_:)método de

Swift Arraytiene un reduce(_:_:)método. reduce(_:_:)tiene la siguiente declaración :

Devuelve el resultado de combinar los elementos de la secuencia usando el cierre dado.

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

El siguiente código de Playground muestra cómo fusionar dos matrices de tipo [Int]en una nueva matriz utilizando el reduce(_:_:)método:

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]

55
gracias por compartir este código, buena explicación, solo agregue a su respuesta, sería mejor, si dice cuál es más eficiente por rendimiento.
kokemomuke

Me gusta +para 2 matrices y joined()para una matriz de matrices.
Cœur

Si está fusionando más de 2 matrices (o cadenas o cualquier otra cosa), no use el +operador, genera tiempos de compilación absolutamente locos.
lawicko

@lawicko, ¿qué método recomendarás?
CyberMew

@CyberMew Cualquier cosa que no use operadores sobrecargados, me gusta el método # 3 porque creo que es más legible, pero también me gusta el método # 4 con el mapa plano. Para las cadenas me gusta el método # 5 porque al final obtienes la cadena unida de inmediato.
lawicko

34

Si no eres un gran fanático de la sobrecarga del operador, o simplemente más de un tipo funcional:

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

Mi método favorito desde Swift 2.0 es aplanar

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

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

Esto regresará, FlattenBidirectionalCollectionasí que si solo quieres un CollectionTypeesto, será suficiente y tendrás una evaluación perezosa de forma gratuita. Si necesita exactamente la matriz, puede hacer esto:

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

2
flatten()Parece que ya no existe. Pero puedes considerarlo joined().
Coeur

13

Para completar la lista de posibles alternativas, reducepodría usarse para implementar el comportamiento de aplanar :

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

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

La mejor alternativa (rendimiento / memoria) entre las presentadas es simplemente flatten , que simplemente envuelva las matrices originales sin crear una nueva estructura de matriz.

Pero tenga en cuenta que aplanar no devuelve unLazyCollection tenga en , de modo que el comportamiento diferido no se propagará a la siguiente operación a lo largo de la cadena (map, flatMap, filter, etc.).

Si pereza tiene sentido en su caso particular, sólo recuerda a anteponer o anexar una .lazya flatten(), por ejemplo, la modificación de la muestra Tomasz esta manera:

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

¿Qué tan bien se mantiene esta respuesta en 2019 con Swift 5.1?
willbattel el

flatten () ya no existe.
join

4

Si desea que la segunda matriz se inserte después de un índice particular, puede hacer esto (a 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] 

4

Swift 3.0

Puede crear una nueva matriz agregando dos matrices existentes con tipos compatibles con el operador de adición ( +). El tipo de la nueva matriz se infiere del tipo de las dos matrices que agrega,

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]

Estos son los resultados correctos de los códigos anteriores.


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

si quieres un resultado como: [1,2,3, [4,5,6]]

arrayOne.append(arrayTwo)

el código anterior convertirá arrayOne como un elemento único y lo agregará al final de arrayTwo.

si quieres un resultado como: [1, 2, 3, 4, 5, 6] entonces,

arrayOne.append(contentsOf: arrayTwo)

el código anterior agregará todos los elementos de arrayOne al final de arrayTwo.

Gracias.


4

Swift 4.X

La forma más fácil que conozco es usar el signo +

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

var Array3 = Array1 + Array2

// Array 3 will just be them combined :)

3

Aquí está la forma más corta de fusionar dos matrices.

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

Concatenar / fusionarlos

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

1

Del mismo modo, con los diccionarios de matrices, uno puede:

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

y puede iterar sobre dict1 y agregar dict2 si la "clave" coincide


0

Matriz de Marge que son diferentes tipos de datos:

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

Salida:

["a", true, 3, "b", "hi", 3, [6]]
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.