Concatenar dos rebanadas en Go


Estoy tratando de combinar el slice [1, 2] y el slice [3, 4]. ¿Cómo puedo hacer esto en Go?

Lo intenté:

append([]int{1,2}, []int{3,4})

Pero consiguió:

cannot use []int literal (type []int) as type int in append

Sin embargo, la documentación parece indicar que esto es posible, ¿qué me estoy perdiendo?

slice = append(slice, anotherSlice...)
Author: icza, 2013-04-27

6 answers

Añadir puntos después del segundo corte:

//---------------------------vvv
append([]int{1,2}, []int{3,4}...)

Esto es como cualquier otra función variádica.

func foo(is ...int) {
    for i := 0; i < len(is); i++ {
        fmt.Println(is[i])
    }
}

func main() {
    foo([]int{9,8,7,6,5}...)
}
 451
Author: 4 revs, 3 users 84%user1106925,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-05 19:40:00

Añadir y copiar segmentos

La función variádica append añade cero o más valores x a s de tipo S, que debe ser un tipo slice, y devuelve el resultado slice, también de tipo S. Los valores x se pasan a un parámetro de type ...T donde T es el tipo de elemento de S y el respectivo se aplican reglas de paso de parámetros. Como caso especial, append también acepta un primer argumento asignable a type []byte con un segundo argumento de string tipo seguido de .... Este formulario añade los bytes de la cadena.

append(s S, x ...T) S  // T is the element type of S

s0 := []int{0, 0}
s1 := append(s0, 2)        // append a single element     s1 == []int{0, 0, 2}
s2 := append(s1, 3, 5, 7)  // append multiple elements    s2 == []int{0, 0, 2, 3, 5, 7}
s3 := append(s2, s0...)    // append a slice              s3 == []int{0, 0, 2, 3, 5, 7, 0, 0}

Pasando argumentos a ... parámetros

Si f es variádico con el tipo de parámetro final ...T, función el argumento es equivalente a un parámetro de tipo []T. En cada llamada de f, el argumento pasado al parámetro final es un nuevo slice of type []T cuyos elementos sucesivos son los argumentos reales, que todo debe ser asignable al tipo T. La longitud de la rebanada es por lo tanto, el número de argumentos vinculados al parámetro final y puede difieren para cada sitio de llamada.

La respuesta a su pregunta es el ejemplo s3 := append(s2, s0...) en la Especificación del Lenguaje de programación Go. Por ejemplo,

s := append([]int{1, 2}, []int{3, 4}...)
 53
Author: peterSO,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-27 12:18:59

Nada en contra de las otras respuestas, pero encontré la breve explicación en los documentos más fácilmente comprensible que los ejemplos en ellos:

Func append

func append(slice []Type, elems ...Type) []Type El accesorio anexar función añade elementos al final de un segmento. Si tiene suficiente capacidad, el destino se resliced para acomodar los nuevos elementos. Si no lo hace, se asignará una nueva matriz subyacente. Anexar devuelve el segmento actualizado. Por consiguiente, es necesario: almacenar el resultado de append, a menudo en la variable que contiene el propio slice:

slice = append(slice, elem1, elem2)
slice = append(slice, anotherSlice...)

Como un caso especial, es legal agregar una cadena a un segmento de bytes, así:

slice = append([]byte("hello "), "world"...)
 23
Author: fiatjaf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-17 02:03:45

Creo que es importante señalar y saber que si el segmento de destino (el segmento al que se agrega) tiene suficiente capacidad, el apéndice se realizará "in-place", reslicando el destino (reslicando a aumente su longitud para poder acomodar los elementos anexables).

Esto significa que si el destino se creó cortando una matriz o un corte más grande que tiene elementos adicionales más allá de la longitud del corte resultante, pueden obtener sobrescribir.

Para demostrar, vea este ejemplo:

a := [10]int{1, 2}
fmt.Printf("a: %v\n", a)

x, y := a[:2], []int{3, 4}
fmt.Printf("x: %v, y: %v\n", x, y)
fmt.Printf("cap(x): %v\n", cap(x))

x = append(x, y...)
fmt.Printf("x: %v\n", x)

fmt.Printf("a: %v\n", a)

Salida (pruébelo en el Go Playground):

a: [1 2 0 0 0 0 0 0 0 0]
x: [1 2], y: [3 4]
cap(x): 10
x: [1 2 3 4]
a: [1 2 3 4 0 0 0 0 0 0]

Creamos un array "backing" a con length 10. Luego creamos la rebanada de destino x cortando esta matriz a, y la rebanada se crea usando el literal compuesto []int{3, 4}. Ahora, cuando agregamos y a x, el resultado es el esperado [1 2 3 4], pero lo que puede ser sorprendente es que la matriz de respaldo {[5] } también cambió, debido a la capacidad de x es 10 que es suficiente para anexarle y, por lo que x es resliced que también usará el mismo array de respaldo a, y append() copiará elementos de y allí.

Si desea evitar esto, puede usar una expresión full slice que tiene la forma

a[low : high : max]

Que construye un slice y también controla la capacidad del slice resultante configurándolo en max - low.

Ver el ejemplo modificado (la única diferencia es que creamos x como esto: x = a[:2:2]:

a := [10]int{1, 2}
fmt.Printf("a: %v\n", a)

x, y := a[:2:2], []int{3, 4}
fmt.Printf("x: %v, y: %v\n", x, y)
fmt.Printf("cap(x): %v\n", cap(x))

x = append(x, y...)
fmt.Printf("x: %v\n", x)

fmt.Printf("a: %v\n", a)

Salida (pruébelo en el Go Playground )

a: [1 2 0 0 0 0 0 0 0 0]
x: [1 2], y: [3 4]
cap(x): 2
x: [1 2 3 4]
a: [1 2 0 0 0 0 0 0 0 0]

Como puede ver, obtenemos el mismo resultado x pero la matriz de respaldo a no cambió, porque la capacidad de x era "solo" 2 (gracias a la expresión full slice a[:2:2]). Así que para hacer el apéndice, se asigna una nueva matriz de respaldo que puede almacenar los elementos de x y y, que es distinta de a.

 13
Author: icza,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-16 21:34:55

append([]int{1,2}, []int{3,4}...) funcionará. Pasando argumentos a parámetros ....

Si f es variadic con un último parámetro p de tipo ...T, entonces dentro de f el tipo de p es equivalente a escribir []T.

Si f se invoca sin argumentos reales para p, el valor pasado a p es nil.

De lo contrario, el valor pasado es un nuevo segmento de tipo []T con una nueva matriz subyacente cuyos elementos sucesivos son los argumentos reales, a los que todos deben asignarse T. La longitud y la capacidad del slice es, por lo tanto, el número de argumentos enlazados a p y pueden diferir para cada sitio de llamada.

Dada la función y las llamadas

func Greeting(prefix string, who ...string)
Greeting("nobody")
Greeting("hello:", "Joe", "Anna", "Eileen")
 0
Author: BaSO4,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-07 08:38:52

Append () and ...

Dos rebanadas se pueden concatenar usando append método en la biblioteca estándar de golang. Que es similar a la operación de la función variadic. Así que necesitamos usar ...

package main

import (
    "fmt"
)

func main() {
    x := []int{1, 2, 3}
    y := []int{4, 5, 6}
    z := append([]int{}, append(x, y...)...)
    fmt.Println(z)
}

La salida del código anterior es: [1 2 3 4 5 6]

 0
Author: ASHWIN RAJEEV,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-10-04 08:52:29