std :: vector <int>があり、n番目の要素を削除したい。それ、どうやったら出来るの?
std::vector<int> vec;
vec.push_back(6);
vec.push_back(-17);
vec.push_back(12);
vec.erase(???);
std :: vector <int>があり、n番目の要素を削除したい。それ、どうやったら出来るの?
std::vector<int> vec;
vec.push_back(6);
vec.push_back(-17);
vec.push_back(12);
vec.erase(???);
回答:
単一の要素を削除するには、次のようにします。
std::vector<int> vec;
vec.push_back(6);
vec.push_back(-17);
vec.push_back(12);
// Deletes the second element (vec[1])
vec.erase(vec.begin() + 1);
または、一度に複数の要素を削除するには:
// Deletes the second through third elements (vec[1], vec[2])
vec.erase(vec.begin() + 1, vec.begin() + 3);
operator+
されていない必然のように、他のコンテナ型のイテレータのために定義されたlist<T>::iterator
(あなたが行うことができないlist.begin() + 2
上std::list
、あなたが使用する必要がありstd::advance
、そのために)
std::find_if
std :: vectorのeraseメソッドはオーバーロードされているので、呼び出す方がおそらく明確です
vec.erase(vec.begin() + index);
単一の要素のみを消去したい場合。
vec.begin()
どちらが有効かがわかります。
vec.erase(0)
が機能しないがvec.erase(vec.begin()+0)
(または+0なしで)機能しないと述べていたらいいのですが それ以外の場合、一致する関数呼び出しを取得できません。これが私がここに来た理由です
vec.erase(0)
は、0
たまたまnullポインタ定数として解釈された場合、実際にコンパイルされる可能性があります...
template <typename T>
void remove(std::vector<T>& vec, size_t pos)
{
std::vector<T>::iterator it = vec.begin();
std::advance(it, pos);
vec.erase(it);
}
template <typename T> void remove(std::vector<T>& vec, size_t pos) { vec.erase(vec.begin + pos); }
私はどちらも優れているとは言っていません。単に個人的な関心を求め、この質問で得られる最良の結果を返すように求めています。
vector<T>::iterator
はランダムアクセスイテレータなので、バージョンは問題なく、おそらく少し明確です。ただし、ランダムアクセスイテレータをサポートしていない別のコンテナにコンテナを変更した場合、Maxが投稿したバージョンは問題なく機能するはずです
実際、このerase
関数は2つのプロファイルで機能します。
単一の要素を削除する
iterator erase (iterator position);
要素の範囲を削除する
iterator erase (iterator first, iterator last);
std :: vec.begin()はコンテナの開始をマークしているため、ベクターのi番目の要素を削除する場合は、次のように使用できます。
vec.erase(vec.begin() + index);
よく見ると、vec.begin()はベクトルの開始位置へのポインタにすぎず、それにiの値を追加すると、i位置へのポインタがインクリメントされるため、代わりに次のようにi番目の要素へのポインタにアクセスできます。
&vec[i]
だから私たちは書くことができます:
vec.erase(&vec[i]); // To delete the ith element
順序付けられていないベクトルがある場合は、順序付けされていないという事実を利用して、CPPCONでDan Higginsから見たものを使用できます。
template< typename TContainer >
static bool EraseFromUnorderedByIndex( TContainer& inContainer, size_t inIndex )
{
if ( inIndex < inContainer.size() )
{
if ( inIndex != inContainer.size() - 1 )
inContainer[inIndex] = inContainer.back();
inContainer.pop_back();
return true;
}
return false;
}
リストの順序は関係ないので、リストの最後の要素を取り、それを削除するアイテムの上にコピーし、最後のアイテムをポップして削除します。
iterator + index
、そのインデックスでのイテレータの位置を実際に返すという前提に依存していません。これは、すべての反復可能なコンテナに当てはまるわけではありません。また、バックポインターを利用することで、線形ではなく一定の複雑さも実現します。
unordered_remove
し、unordered_remove_if
それがされていると私はそれを逃した場合を除き、これらの日より多くの頻繁に起こっているれ、... :)
std::remove
並べ替える削除するすべての要素が最後であるので、そのコンテナ、あなたがC ++ 17を使用している場合は、次のように手動でそれを行うには必要はありません
std::remove
役立ちますか?cppreferenceは、C ++ 17でも、すべてのremove
オーバーロードには述語が必要であり、インデックスを取得するものはないと主張しています。
大きなベクトル(サイズ> 100,000)で作業していて、たくさんの要素を削除したい場合は、次のようにすることをお勧めします。
int main(int argc, char** argv) {
vector <int> vec;
vector <int> vec2;
for (int i = 0; i < 20000000; i++){
vec.push_back(i);}
for (int i = 0; i < vec.size(); i++)
{
if(vec.at(i) %3 != 0)
vec2.push_back(i);
}
vec = vec2;
cout << vec.size() << endl;
}
このコードは、3で割り切れないvec内のすべての数値を取り、それをvec2にコピーします。その後、vec2をvecにコピーします。かなり速いです。20,000,000の要素を処理するために、このアルゴリズムは0.8秒しかかかりません!
消去方法でも同じことを行いましたが、それには非常に時間がかかりました。
Erase-Version (10k elements) : 0.04 sec
Erase-Version (100k elements) : 0.6 sec
Erase-Version (1000k elements): 56 sec
Erase-Version (10000k elements): ...still calculating (>30 min)
要素を削除するには、次の方法を使用します。
// declaring and assigning array1
std:vector<int> array1 {0,2,3,4};
// erasing the value in the array
array1.erase(array1.begin()+n);
より広範な概要については、http://www.cplusplus.com/reference/vector/vector/erase/をご覧ください。
私はそれがあなたが探しているものだと思うので、これを読むことをお勧めします。https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom
たとえば使用する場合
vec.erase(vec.begin() + 1, vec.begin() + 3);
ベクトルのn番目の要素を消去しますが、2番目の要素を消去すると、ベクトルの他のすべての要素がシフトされ、ベクトルのサイズが-1になります。ベクトルsize()が減少しているため、ベクトルをループする場合、これは問題になる可能性があります。この提供されたリンクのような問題がある場合は、標準C ++ライブラリの既存のアルゴリズムを使用することをお勧めします。および「remove」または「remove_if」。
これが役に立てば幸い
上記の回答では、常に署名付きインデックスがあると想定しています。悲しいことに、索引付けにstd::vector
使用size_type
し、difference_type
イテレータの計算「-Wconversion」とフレンドが有効になっている場合、これらは一緒に機能しません。これは、署名付きと署名なしの両方を処理できる一方で、質問に答える別の方法です。
削除する:
template<class T, class I, class = typename std::enable_if<std::is_integral<I>::value>::type>
void remove(std::vector<T> &v, I index)
{
const auto &iter = v.cbegin() + gsl::narrow_cast<typename std::vector<T>::difference_type>(index);
v.erase(iter);
}
取る:
template<class T, class I, class = typename std::enable_if<std::is_integral<I>::value>::type>
T take(std::vector<T> &v, I index)
{
const auto &iter = v.cbegin() + gsl::narrow_cast<typename std::vector<T>::difference_type>(index);
auto val = *iter;
v.erase(iter);
return val;
}
これを行うには、ベクター内の値を使用して要素を削除する場合にこれを実行するもう1つの方法があります。これは、ベクター上で実行するだけです。
vector<int> ar(n);
ar.erase(remove(ar.begin(), ar.end()), (place your value here from vector array));
ここから値が削除されます。ありがとう
最速の方法(時間によるプログラミングコンテストの複雑さ()=定数)
1秒で100Mのアイテムを消去できます。
vector<int> it = (vector<int>::iterator) &vec[pos];
vec.erase(it);
そして最も読みやすい方法:
vec.erase(vec.begin() + pos);
vector<int>::iterator
必ずしも同じではありませんint *