Saya memiliki std :: vector <int>, dan saya ingin menghapus elemen ke-n. Bagaimana aku melakukan itu?
std::vector<int> vec;
vec.push_back(6);
vec.push_back(-17);
vec.push_back(12);
vec.erase(???);
Saya memiliki std :: vector <int>, dan saya ingin menghapus elemen ke-n. Bagaimana aku melakukan itu?
std::vector<int> vec;
vec.push_back(6);
vec.push_back(-17);
vec.push_back(12);
vec.erase(???);
Jawaban:
Untuk menghapus satu elemen, Anda dapat melakukan:
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);
Atau, untuk menghapus lebih dari satu elemen sekaligus:
// Deletes the second through third elements (vec[1], vec[2])
vec.erase(vec.begin() + 1, vec.begin() + 3);
operator+
yang tidak tentu didefinisikan untuk iterator pada jenis wadah lainnya, seperti list<T>::iterator
(Anda tidak dapat melakukan list.begin() + 2
pada std::list
, Anda harus menggunakan std::advance
untuk itu)
std::find_if
Metode hapus pada std :: vector kelebihan beban, jadi mungkin lebih jelas untuk memanggil
vec.erase(vec.begin() + index);
ketika Anda hanya ingin menghapus satu elemen.
vec.begin()
yang valid.
vec.erase(0)
tidak berfungsi, tetapi vec.erase(vec.begin()+0)
(atau tanpa +0) tidak. Kalau tidak, saya tidak mendapatkan panggilan fungsi yang cocok, itulah sebabnya saya datang ke sini
vec.erase(0)
sebenarnya dapat dikompilasi jika 0
kebetulan ditafsirkan sebagai konstanta penunjuk nol ...
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); }
Saya tidak mengatakan keduanya lebih baik, hanya meminta karena minat pribadi dan mengembalikan hasil terbaik yang bisa didapat pertanyaan ini.
vector<T>::iterator
adalah iterator akses acak, versi Anda baik-baik saja dan mungkin sedikit lebih jelas. Tetapi versi yang diposting Max akan bekerja dengan baik jika Anda mengganti wadah ke wadah lain yang tidak mendukung iterator akses acak
The erase
Metode yang akan digunakan dalam dua cara:
Menghapus elemen tunggal:
vector.erase( vector.begin() + 3 ); // Deleting the fourth element
Menghapus berbagai elemen:
vector.erase( vector.begin() + 3, vector.begin() + 5 ); // Deleting from fourth element to sixth element
Sebenarnya, erase
fungsi ini berfungsi untuk dua profil:
Menghapus satu elemen
iterator erase (iterator position);
Menghapus serangkaian elemen
iterator erase (iterator first, iterator last);
Karena std :: vec.begin () menandai awal dari wadah dan jika kita ingin menghapus elemen ke-i dalam vektor kita, kita dapat menggunakan:
vec.erase(vec.begin() + index);
Jika Anda melihat lebih dekat, vec.begin () hanyalah sebuah pointer ke posisi awal vektor kita dan menambahkan nilai i ke dalamnya akan menambah pointer ke posisi i, jadi alih-alih kita dapat mengakses pointer ke elemen engan dengan:
&vec[i]
Jadi kita bisa menulis:
vec.erase(&vec[i]); // To delete the ith element
Jika Anda memiliki vektor tidak berurutan, Anda dapat memanfaatkan fakta bahwa itu tidak berurutan dan menggunakan sesuatu yang saya lihat dari Dan Higgins di CPPCON
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;
}
Karena urutan daftar tidak masalah, ambil saja elemen terakhir dalam daftar dan salin ke atas item yang ingin Anda hapus, lalu pop dan hapus item terakhir.
iterator + index
benar-benar akan memberi Anda kembali posisi iterator pada indeks itu, yang tidak berlaku untuk semua wadah yang dapat diubah. Ini juga merupakan kompleksitas konstan daripada linier dengan mengambil keuntungan dari pointer belakang.
unordered_remove
dan unordered_remove_if
... kecuali jika sudah dan saya melewatkannya, yang terjadi lebih dan lebih sering akhir-akhir ini :)
std::remove
atur ulang wadah sehingga semua elemen yang akan dihapus ada di akhir, tidak perlu melakukannya secara manual seperti ini jika Anda menggunakan C ++ 17.
std::remove
membantu? cppreference mengklaim bahwa bahkan di C ++ 17, semua remove
overload memerlukan predikat, dan tidak ada yang mengambil indeks.
Jika Anda bekerja dengan vektor besar (ukuran> 100.000) dan ingin menghapus banyak elemen, saya akan merekomendasikan untuk melakukan sesuatu seperti ini:
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;
}
Kode mengambil setiap angka dalam vec yang tidak dapat dibagi dengan 3 dan menyalinnya ke vec2. Setelah itu menyalin vec2 di vec. Cukup cepat. Untuk memproses 20.000.000 elemen, algoritma ini hanya membutuhkan 0,8 detik!
Saya melakukan hal yang sama dengan metode erase, dan itu membutuhkan banyak waktu:
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)
Untuk menghapus elemen gunakan cara berikut:
// declaring and assigning array1
std:vector<int> array1 {0,2,3,4};
// erasing the value in the array
array1.erase(array1.begin()+n);
Untuk gambaran umum yang lebih luas, Anda dapat mengunjungi: http://www.cplusplus.com/reference/vector/vector/erase/
Saya sarankan untuk membaca ini karena saya percaya itulah yang Anda cari. https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom
Jika Anda menggunakan misalnya
vec.erase(vec.begin() + 1, vec.begin() + 3);
Anda akan menghapus elemen ke-n vektor tetapi ketika Anda menghapus elemen kedua, semua elemen vektor lainnya akan digeser dan ukuran vektor akan menjadi -1. Ini bisa menjadi masalah jika Anda mengulang vektor karena ukuran vektor () menurun. Jika Anda memiliki masalah seperti tautan yang disediakan ini, disarankan untuk menggunakan algoritma yang ada di pustaka C ++ standar. dan "hapus" atau "hapus_kan".
Semoga ini bisa membantu
Jawaban sebelumnya mengasumsikan bahwa Anda selalu memiliki indeks yang ditandatangani. Sayangnya, std::vector
kegunaan size_type
untuk pengindeksan, dan difference_type
untuk iterator aritmatika, sehingga mereka tidak bekerja bersama jika Anda memiliki "-Konversi" dan teman diaktifkan. Ini adalah cara lain untuk menjawab pertanyaan, sambil dapat menangani keduanya yang ditandatangani dan tidak ditandatangani:
Untuk menghapus:
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);
}
Untuk mengambil:
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;
}
di sini adalah satu lagi cara untuk melakukan ini jika Anda ingin menghapus elemen dengan menemukan ini dengan nilainya dalam vektor, Anda hanya perlu melakukan ini pada vektor.
vector<int> ar(n);
ar.erase(remove(ar.begin(), ar.end()), (place your value here from vector array));
itu akan menghapus nilai Anda dari sini. Terima kasih
cara tercepat (untuk kontes pemrograman dengan kompleksitas waktu () = konstan)
dapat menghapus item 100M dalam 1 detik;
vector<int> it = (vector<int>::iterator) &vec[pos];
vec.erase(it);
dan cara yang paling mudah dibaca:
vec.erase(vec.begin() + pos);
vector<int>::iterator
belum tentu sama denganint *