削除方法: 1. スライスをインターセプトして指定された要素を削除します。構文は「append(a[:i], a[i 1:]...)」です。 2. 新しいスライスを作成し、削除する要素をフィルタリングして除外し、それらを新しいスライスに割り当てます。 3. 添字インデックスを使用して、有効な要素があるべき位置を記録します。すべての要素を走査し、有効な要素が見つかったら、それをインデックスに移動し、インデックスを 1 つ増やします。最終的なインデックス位置は、すべての要素の次の位置になります。有効な要素を選択し、最後にインターセプトを行います。
このチュートリアルの動作環境: Windows 7 システム、GO バージョン 1.18、Dell G3 コンピューター。
Go にはスライス要素を削除するための特別な構文や関数が用意されていないため、要素を削除するにはスライス自体の特性を使用する必要があります。
スライス内の指定要素を削除するには一般的に以下のような方法がありますが、本記事では[]intを例に具体的な実装を示します。
1. インターセプト方法 (元のスライスを変更する)
ここでは、スライスのインターセプトを使用して、指定された要素を削除します。削除する場合、次の要素が前に移動されるため、添え字 i を 1 つ左に移動する必要があることに注意してください。
// DeleteSlice1 删除指定元素。 func DeleteSlice1(a []int, elem int) []int { for i := 0; i < len(a); i++ { if a[i] == elem { a = append(a[:i], a[i+1:]...) i-- } } return a }
2. コピー方法 (元のスライスを変更せずに)
この方法が最も理解しやすいです。スライスを再利用して削除します。 . 要素がフィルターで除外されます。欠点は、別のスライス用にスペースを空ける必要があることですが、利点は、理解しやすく、元のスライスを変更しないことです。
// DeleteSlice2 删除指定元素。 func DeleteSlice2(a []int, elem int) []int { tmp := make([]int, 0, len(a)) for _, v := range a { if v != elem { tmp = append(tmp, v) } } return tmp }
3. Shift メソッド (元のスライスを変更)
#3.1 メソッド 1
使用次の有効な要素が存在する位置を記録する添字インデックス。すべての要素を走査し、有効な要素が見つかったら、それをインデックスに移動し、インデックスを 1 つ増やします。最終的なインデックス位置はすべての有効な要素の次の位置であり、最終的にはインターセプトで十分です。このメソッドは元のスライスを変更します。
この方法は、要素を移動する必要があるたびにパフォーマンスが向上するため、最初のインターセプト方法を改良したものとみなすことができます。
// DeleteSlice3 删除指定元素。 func DeleteSlice3(a []int, elem int) []int { j := 0 for _, v := range a { if v != elem { a[j] = v j++ } } return a[:j] }
3.2 メソッド 2
スライスを作成しますが、元のスライスの基礎となる配列を共有します。この方法では、追加のメモリ空間を割り当てる必要がなく、元のスライスに直接変更を加えることができます。
// DeleteSlice4 删除指定元素。 func DeleteSlice4(a []int, elem int) []int { tgt := a[:0] for _, v := range a { if v != elem { tgt = append(tgt, v) } } return tgt }
4. パフォーマンスの比較
スライスに 0 と 1 があり、すべての 0 を削除するとします。
ここでは、長さ 10、100、および 1000 のスライスをテストして、上記 4 つの実装のパフォーマンスの違いを比較します。
生成されたスライス関数は次のとおりです:
func getSlice(n int) []int { a := make([]int, 0, n) for i := 0; i < n; i++ { if i%2 == 0 { a = append(a, 0) continue } a = append(a, 1) } return a }
ベンチマーク テストのコードは次のとおりです:
func BenchmarkDeleteSlice1(b *testing.B) { for i := 0; i < b.N; i++ { _ = DeleteSlice1(getSlice(10), 0) } } func BenchmarkDeleteSlice2(b *testing.B) { for i := 0; i < b.N; i++ { _ = DeleteSlice2(getSlice(10), 0) } } func BenchmarkDeleteSlice3(b *testing.B) { for i := 0; i < b.N; i++ { _ = DeleteSlice3(getSlice(10), 0) } } func BenchmarkDeleteSlice4(b *testing.B) { for i := 0; i < b.N; i++ { _ = DeleteSlice4(getSlice(10), 0) } }
テスト結果は次のとおりです:
The元のスライスの長さは 10 です:
go test -bench=. main/slice goos: windows goarch: amd64 pkg: main/slice cpu: Intel(R) Core(TM) i7-9700 CPU @ 3.00GHz BenchmarkDeleteSlice1-8 17466486 65.07 ns/op BenchmarkDeleteSlice2-8 14897282 85.22 ns/op BenchmarkDeleteSlice3-8 21952129 50.78 ns/op BenchmarkDeleteSlice4-8 22176390 54.68 ns/op PASS ok main/slice 5.427s
元のスライスの長さは 100 です:
BenchmarkDeleteSlice1-8 1652146 762.1 ns/op BenchmarkDeleteSlice2-8 2124237 578.4 ns/op BenchmarkDeleteSlice3-8 3161318 359.9 ns/op BenchmarkDeleteSlice4-8 2714158 423.7 ns/op
元のスライスの長さは 1000 です:
BenchmarkDeleteSlice1-8 56067 21915 ns/op BenchmarkDeleteSlice2-8 258662 5007 ns/op BenchmarkDeleteSlice3-8 432049 2724 ns/op BenchmarkDeleteSlice4-8 325194 3615 ns/op
5
ベンチマーク テストの結果から判断すると、最もパフォーマンスが良いのはシフト方式であり、最初の実装方式の方が優れています。最もパフォーマンスが低く、最も一般的に使用される方法はインターセプト方法です。スライス長が増加するにつれて、上記の 4 つの削除方法のパフォーマンスの違いがより明確になります。
実際の使用では、さまざまなシナリオに応じて選択できます。 copy メソッドを使用して元のスライスを変更できない場合は、shift メソッドの最初の実装方法を使用して元のスライスを変更できます。
【関連する推奨事項: Go ビデオ チュートリアル 、プログラミング教育 】
以上がGo言語でスライスから要素を削除する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。