recursive golang for example go append slice variadic-functions

golang - Concatenar dos rebanadas en Go



interface en golang (6)

Estoy tratando de combinar la división [1, 2] y la división [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 falta?

slice = append(slice, anotherSlice...)


Anexando y copiando cortes

La función variadic adjunta agrega cero o más valores x a s de tipo S , que debe ser un tipo de sector, y devuelve el sector resultante, también del tipo S Los valores x se pasan a un parámetro de tipo ...T donde T es el tipo de elemento de S y se aplican las respectivas reglas de paso de parámetros. Como caso especial, anexar también acepta un primer argumento asignable al tipo []byte con un segundo argumento de tipo string seguido de ... Esta forma anexa 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 variable con el tipo de parámetro final ...T , entonces dentro de la 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 una nueva porción del tipo []T cuyos elementos sucesivos son los argumentos reales, que todos deben ser asignables al tipo T La longitud de la división es, por lo tanto, el número de argumentos vinculados al parámetro final y puede diferir 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}...)


Operador de propagación y función append ()

Se pueden concatenar dos segmentos utilizando el método de adición en la biblioteca estándar de Golang. Que es similar a la variadic 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]


Agregue puntos después de la segunda rebanada:

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

Esto es como cualquier otra función variada.

func foo(is ...int) { for i := 0; i < len(is); i++ { fmt.Println(is[i]) } } func main() { foo([]int{9,8,7,6,5}...) }


Creo que es importante señalar y saber que si la división de destino (la división a la que se agrega) tiene capacidad suficiente, la adición se realizará "en el lugar", al dividir el destino (volver a dividir para aumentar su longitud para poder ser capaz de acomodar los elementos anexables).

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

Para demostrarlo, 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ébalo 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 una matriz de "respaldo" con longitud 10 . Luego creamos el segmento de destino x dividiendo esto en a matriz, el segmento y se crea utilizando 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 sorprender es que la matriz de respaldo a también cambió, porque la capacidad de x es 10 que es suficiente para añadir y , así que x es reslicado, que también usará la misma matriz de respaldo, y append() copiará los elementos de y allí.

Si desea evitar esto, puede usar una expresión de sector completa que tiene el formulario

a[low : high : max]

que construye una porción y también controla la capacidad de la porción resultante configurándola en max - low .

Vea el ejemplo modificado (la única diferencia es que creamos x así: 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ébalo 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 de x pero la matriz de respaldo a no cambió, porque la capacidad de x era "solo" 2 (gracias a la expresión de corte completo a[:2:2] ). Así que para hacer el anexo, se asigna una nueva matriz de respaldo que puede almacenar los elementos tanto de x como de y , lo que es distinto de a .


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

función adjuntar

func append(slice []Type, elems ...Type) []Type La función incorporada append agrega elementos al final de una división. Si tiene capacidad suficiente, el destino se vuelve a segmentar para acomodar los nuevos elementos. Si no lo hace, se asignará una nueva matriz subyacente. Anexar devuelve la porción actualizada. Por lo tanto, es necesario almacenar el resultado de la anexión, a menudo en la variable que contiene la propia porción:

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

Como caso especial, es legal agregar una cadena a un segmento de bytes, como este:

slice = append([]byte("hello "), "world"...)


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

Si f es variable con un parámetro final p de tipo ...T , entonces dentro de f el tipo de p es equivalente a tipo []T

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

De lo contrario, el valor pasado es una nueva porción de tipo []T con una nueva matriz subyacente cuyos elementos sucesivos son los argumentos reales, que todos deben ser asignables a T La longitud y la capacidad de la porción 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")