C ++で値によって要素を削除するという質問に対するこの回答に出くわしました:
基本的:
vec.erase(std::remove(vec.begin(), vec.end(), valueToRemove), vec.end());
答えは一理ありますが、これはスタイルが悪いのではないですか?ロジックは二重否定で構成されています...これを行うためのよりクリーンな方法はありますか?
C ++で値によって要素を削除するという質問に対するこの回答に出くわしました:
基本的:
vec.erase(std::remove(vec.begin(), vec.end(), valueToRemove), vec.end());
答えは一理ありますが、これはスタイルが悪いのではないですか?ロジックは二重否定で構成されています...これを行うためのよりクリーンな方法はありますか?
コレクションからの要素の削除は、次の 2 つの手順で構成されます。
C++ 標準ライブラリでは、これらはそれぞれremove
との 2 つの別個の関数erase
です。
確かに、より使いやすい関数のタイプを想像することはできerase_if
ますが、明らかに現在のコードで十分であると考えられています。もちろん、自分で書くこともできますremove_if
。
これは悪くなく、実際、線形時間の条件に基づいてベクトルから要素を削除する効率的な方法です。この動画の 35 分からご覧ください。Erase and Remove Idiom の STL の説明
コンテナーにはさまざまな種類があることに注意してください: 連続 vs ノードベース、順次 vs 連想。
ノードベースのコンテナーにより、効率的な消去/挿入が可能になります。シーケンシャル コンテナは要素を挿入順序 (つまり位置) で編成しますが、連想コンテナは要素を (キー) 値で編成します。
現在のすべての連想コンテナー (マップ/セット/順序なし) はノードベースであり、それらを使用して要素を直接消去でき、要素ごとのメンバーerase
関数を直接使用する必要があります。リストはノードベースのシーケンス コンテナーであるため、個々の要素を効率的に消去できますが、値による要素の検索には直線的な時間がかかります。これが、リストがメンバーremove
関数を提供する理由です。値によって要素を消去する簡単な方法がないのは、シーケンス コンテナー (ベクターおよびデキュー) だけです。 そこで、フリーremove
アルゴリズムが登場します。このアルゴリズムは、最初にシーケンスを再配置erase
し、コンテナーのメンバーがコンテナーの最後で効率的な消去を実行できるようにします。
基礎となるコンテナの知識がなくても機能する標準ライブラリの多くの一般的な側面とは異なり、コピー/消去のイディオムは、コンテナ間の違いについて少し詳細な知識を必要とするものの 1 つです。