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(std::next(vec.begin()));
または、一度に複数の要素を削除するには:
// Deletes the second through third elements (vec[1], vec[2])
vec.erase(std::next(vec.begin(), 1), std::next(vec.begin(), 3));
std::vector の erase メソッドはオーバーロードされているため、おそらく呼び出す方が明確です
vec.erase(vec.begin() + index);
単一の要素のみを消去したい場合。
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);
}
このeraseメソッドは、次の 2 つの方法で使用されます。
単一要素の消去:
vector.erase( vector.begin() + 3 ); // Deleting the fourth element
要素の消去範囲:
vector.erase( vector.begin() + 3, vector.begin() + 5 ); // Deleting from fourth element to sixth element
実際、この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
一部の人にとっては明らかなように思えるかもしれませんが、上記の回答を詳しく説明すると、次のようになります。
std::vectorベクター全体のループを使用して要素の削除を行っている場合はerase、ベクターを逆の順序で処理する必要があります。
for (int i = v.size() - 1; i >= 0; i--)
(クラシック)の代わりに
for (int i = 0; i < v.size(); i++)
その理由は、インデックスが影響を受けるeraseためです。4 番目の要素を削除すると、前の 5 番目の要素が新しい 4 番目の要素になり、実行している場合はループによって処理されませんi++。
以下は、int ベクトルのオッズ要素をすべて削除したい場合の簡単な例です。
#include <iostream>
#include <vector>
using namespace std;
void printVector(const vector<int> &v)
{
for (size_t i = 0; i < v.size(); i++)
{
cout << v[i] << " ";
}
cout << endl;
}
int main()
{
vector<int> v1, v2;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
v2.push_back(i);
}
// print v1
cout << "v1: " << endl;
printVector(v1);
cout << endl;
// print v2
cout << "v2: " << endl;
printVector(v2);
// Erase all odd elements
cout << "--- Erase odd elements ---" << endl;
// loop with decreasing indices
cout << "Process v2 with decreasing indices: " << endl;
for (int i = v2.size() - 1; i >= 0; i--)
{
if (v2[i] % 2 != 0)
{
cout << "# ";
v2.erase(v2.begin() + i);
}
else
{
cout << v2[i] << " ";
}
}
cout << endl;
cout << endl;
// loop with increasing indices
cout << "Process v1 with increasing indices: " << endl;
for (int i = 0; i < v1.size(); i++)
{
if (v1[i] % 2 != 0)
{
cout << "# ";
v1.erase(v1.begin() + i);
}
else
{
cout << v1[i] << " ";
}
}
return 0;
}
出力:
v1:
0 1 2 3 4 5 6 7 8 9
v2:
0 1 2 3 4 5 6 7 8 9
--- Erase odd elements ---
Process v2 with decreasing indices:
# 8 # 6 # 4 # 2 # 0
Process v1 with increasing indices:
0 # # # # #
インデックスが増加する 2 番目のバージョンでは、偶数はスキップされるため表示されないことに注意してください。i++
逆の順序でベクトルを処理することにも注意してください。インデックスに符号なしの型を使用することはできません (動作for (uint8_t i = v.size() -1; ...しません)。これは、iequalsがオーバーフローして、たとえばと等しいためです (そのため、ループは停止せず、ベクトルの範囲外になる可能性があります)。0i--255uint8_ti>= 0
要素を削除するには、次の方法を使用します。
// 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/ をご覧ください。
前の回答では、常に署名付きインデックスがあることを前提としています。悲しいことに、インデックス作成とイテレータ演算にstd::vector使用されるため、「-Wconversion」とフレンドが有効になっている場合、それらは一緒に機能しません。これは、署名付きと未署名の両方を処理できる一方で、質問に答える別の方法です。size_typedifference_type
削除する:
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;
}