ホームページ  >  記事  >  バックエンド開発  >  Go でスライスから要素を効率的に削除するにはどうすればよいですか?

Go でスライスから要素を効率的に削除するにはどうすればよいですか?

PHPz
PHPz転載
2024-02-08 22:03:22690ブラウズ

如何在 Go 中高效地从切片中删除元素?

php エディター Apple は、Go でスライスから要素を効率的に削除する方法を紹介します。 Go言語ではスライス内の要素を削除するのが一般的な操作ですが、スライスの特性上、要素を直接削除するとスライスの長さが変化し、その後の操作に影響を与える場合があります。スライス内の要素を効率的に削除するには、スライスの特性といくつかの組み込み関数を使用してこれを実現します。一般的に使用されるいくつかの方法については、以下で詳しく紹介します。

質問内容

スライス要素を削除する方法は複数あります。しかし、スライスを大量に処理するアプリケーションがある場合はどうなるでしょうか? Go スライスは新しい要素を追加するために適切に最適化されていますが、スライスから要素を削除する効率的な方法はありますか (速度だけでなくメモリも最適化されます)。

Go 1.21 で導入されたスライス.削除関数は知っていますが、舞台裏では次のよく知られたテクニックが使用されています。 リーリー

この場合、基になる配列は縮小されないようです。これは速度の観点からは優れていますが、多数の要素 (100k や 1M など) があり、それらを非常に少数 (わずか 10 個など) に減らした場合はどうなるでしょうか?スライス容量を増やすために使用されるようなメモリの最適化はないようです。

スライス内の要素の順序を保持する必要がない場合は、次の方法を使用できます (プレイグラウンド リンクに移動):

リーリー

これは、大きなスライスと少数の要素を削除する場合に便利です (その背後にある考え方は、少数のスライス要素をコピーすることです)。

メモリに関してはどちらも容量は同じで減りません。例えば:### リーリー

それでは、メモリ使用量を最適化する方法はあるのでしょうか?たとえば、スライスの長さが容量の半分未満の場合は、容量を半分に減らします。

これを効率的に行う方法も知りたいです。たとえば、このようなテクニック

s[:len(s):len(s)]

(slices.Clip で使用される完全なスライス式)これは、基礎となる配列を削減しません。(この提案で述べたように) 新しい要素を子スライスに追加するときに、親スライス要素の上書きを避けるために、スライス構造に新しい容量を保持するだけです。 解決策

「一般的に最適な」解決策はありません。質問の中で複数のアプローチが示されていますが、特定のシナリオでは、それぞれのアプローチが他のアプローチよりも優れている可能性があります。

このような状況に遭遇した場合、多数の要素の中からいくつかの要素を残しておきたい場合は、それらの要素の削除を開始しないでください。これらの要素を使用して新しいスライスを構築します。これにより、高速化に加えて、メモリの問題も確実に解決されます。

新しいスライスを割り当てて使用する以外に、完全なスライス式を使用してメモリ使用量を削減することはできません。バッキング配列への参照がある限り、それは縮小しません (少なくとも Go の現在のバージョンでは)。大きなバッキング配列が割り当てられているものの、その一部しか使用されていない状況が発生した場合は、新しいスライスを割り当て、要素を手動でコピーして、大きな配列をガベージ コレクションできるようにすることができます。

また、多くの要素を削除する必要がある大きなスライスがある場合、スライスは使用するのに最適なデータ構造ではない可能性があることも考慮してください。たとえば、リンク リストを使用してみたり、マップを試してみたりすることもできます。リンク リストまたはマップから要素を削除する方がはるかに高速であり、マップも高速な (

O(n)

) バーの下に示すように、ルックアップ時間。

以上がGo でスライスから要素を効率的に削除するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はstackoverflow.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。