web-dev-qa-db-ja.com

Goで2つのスライスを連結する

スライス[1, 2]とスライス[3, 4]を結合しようとしています。 Goでこれを行うにはどうすればいいですか。

私は試した:

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

しかし:

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

しかし、 ドキュメンテーション はこれが可能であることを示しているようですが、足りないものは何ですか?

slice = append(slice, anotherSlice...)
349
Kevin Burke

2番目のスライスの後にドットを追加します。

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

これは他の可変基数関数とまったく同じです。

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

func main() {
    foo([]int{9,8,7,6,5}...)
}
585
user1106925

スライスを追加してコピーする

可変関数appendは、x型のsにゼロ個以上の値Sを追加し、スライス型でなければならず、結果として得られるスライスもS型で返します。値x...T型のパラメータに渡されます。ここでTSの要素型であり、それぞれのパラメータ引き渡し規則が適用されます。特別な場合として、appendはstring型の第2引数とそれに続く[]byteの型...に代入可能な第1引数も受け入れます。この形式は文字列のバイトを追加します。

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}

... parametersに引数を渡す

fが最終パラメータ型...Tの可変長である場合、関数内では引数は型[]Tのパラメータと同等です。 fが呼び出されるたびに、最後のパラメータに渡される引数は、連続する要素が実際の引数である[]T型の新しいスライスです。これらはすべてT型に代入可能である必要があります。スライスの長さは、したがって、最後のパラメータにバインドされた引数の数であり、コールサイトごとに異なります。

あなたの質問に対する答えは Goプログラミング言語仕様 の中の例s3 := append(s2, s0...)です。例えば、

s := append([]int{1, 2}, []int{3, 4}...)
60
peterSO

他の答えに反することは何もありませんが、 docs に簡単な説明があります。

func append

func append(slice []Type, elems ...Type) []Type append組み込み関数はスライスの最後に要素を追加します。十分な容量がある場合は、新しい要素に対応するために宛先が再スライスされます。そうでない場合は、新しい基になる配列が割り当てられます。 Appendは更新されたスライスを返します。したがって、appendの結果をスライス自体を保持する変数に格納する必要があります。

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

特別な場合として、次のようにバイトスライスに文字列を追加することは正当です。

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

宛先スライス(追加するスライス)に十分な容量がある場合、宛先を再スライスすることによりincrease追加可能な要素を収容できるようにするための長さ)。

これは、結果のスライスの長さを超える追加要素を持つ大きな配列またはスライスをスライスすることによって宛先が作成された場合、それらが上書きされる可能性があることを意味します。

例を示すには、次の例を参照してください。

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)

出力( 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]

長さ10の「バッキング」配列aを作成しました。次に、このx配列をスライスしてa宛先スライスを作成し、複合リテラル[]int{3, 4}を使用してyスライスを作成します。ここでyxに追加すると、結果は期待される[1 2 3 4]になりますが、驚くべきことは、aの容量が10であり、これがxを追加するのに十分なためですそれで、同じyバッキング配列を使用するxが再スライスされ、append()aの要素をそこにコピーします。

これを避けたい場合は、 full slice expression の形式を使用できます。

a[low : high : max]

スライスを構築し、max - lowに設定することで、結果のスライスの容量も制御します。

変更された例を参照してください(唯一の違いは、x = a[:2:2]:のようにyを作成することです。

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)

出力( 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]

ご覧のとおり、同じxの結果が得られますが、xの容量は「のみ」であるため、バッキング配列aは変更されませんでした2(完全なスライス式a[:2:2]のおかげ)。したがって、追加を行うために、xxとは異なるyaの両方の要素を格納できる新しいバッキング配列が割り当てられます。

20
icza

append()関数とスプレッド演算子

2つのスライスは標準のgolangライブラリのappendメソッドを使って連結できます。これはvariadic関数操作に似ています。だから私たちは...を使う必要があります

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)
}

上記のコードの出力は次のとおりです。[1 2 3 4 5 6]

4
ASHWIN RAJEEV

append([]int{1,2}, []int{3,4}...)は動作します。 ...パラメータに引数を渡す.

fが、タイプ...Tの最終パラメーターpを使用して可変長である場合、f内では、タイプpはタイプ[]Tと同等です。

fに実際の引数を指定せずにpが呼び出された場合、pに渡される値はnilです。

それ以外の場合、渡される値は連続する要素が実際の引数であるすべてのTに代入可能である必要がある新しい基底配列を持つタイプ[]Tの新しいスライスです。したがって、スライスの長さと容量はpにバインドされている引数の数であり、呼び出しサイトごとに異なる可能性があります。

与えられた機能と呼び出し

func Greeting(prefix string, who ...string)
Greeting("nobody")
Greeting("hello:", "Joe", "Anna", "Eileen")
1
BaSO4