Bir std :: vector <int> var ve n'th öğeyi silmek istiyorum. Bunu nasıl yaparım?
std::vector<int> vec;
vec.push_back(6);
vec.push_back(-17);
vec.push_back(12);
vec.erase(???);
Bir std :: vector <int> var ve n'th öğeyi silmek istiyorum. Bunu nasıl yaparım?
std::vector<int> vec;
vec.push_back(6);
vec.push_back(-17);
vec.push_back(12);
vec.erase(???);
Yanıtlar:
Tek bir öğeyi silmek için şunları yapabilirsiniz:
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);
Veya aynı anda birden fazla öğeyi silmek için:
// Deletes the second through third elements (vec[1], vec[2])
vec.erase(vec.begin() + 1, vec.begin() + 3);
operator+edilir değil ille gibi diğer konteyner türlerinde yineleyiciler için tanımlanan list<T>::iterator(yapamayacağınız list.begin() + 2bir de std::list, kullanmak zorunda std::advanceolduğu için)
std::find_if
Std :: vector'daki silme yöntemi aşırı yüklenmiş, bu nedenle aramak daha açıktır
vec.erase(vec.begin() + index);
yalnızca tek bir öğeyi silmek istediğinizde.
vec.begin()geçerli olanı alırsınız .
vec.erase(0)işe yaramazsa bahsetmişti , ama vec.erase(vec.begin()+0)(ya da +0 olmadan). Aksi takdirde, eşleşen bir işlev çağrısı
vec.erase(0)gerçekten derlenebilir 0...
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); }Ben sadece daha iyi olduğunu söylemiyorum, sadece kişisel çıkarlarını sormak ve bu sorunun elde edebileceği en iyi sonucu döndürmek.
vector<T>::iteratora rastgele erişimli bir yineleyici olduğundan, sürümünüz gayet iyi ve belki biraz daha net. Ancak, kapsayıcıyı rasgele erişimli yineleyicileri desteklemeyen bir başkasına değiştirirseniz, Max'in yayınladığı sürüm gayet iyi çalışmalıdır
eraseYöntem iki şekilde kullanılacaktır:
Tek eleman silme:
vector.erase( vector.begin() + 3 ); // Deleting the fourth elementEleman aralığının silinmesi:
vector.erase( vector.begin() + 3, vector.begin() + 5 ); // Deleting from fourth element to sixth elementAslında, erasefonksiyon iki profil için çalışır:
Tek bir öğeyi kaldırma
iterator erase (iterator position);Bir dizi öğeyi kaldırma
iterator erase (iterator first, iterator last);Std :: vec.begin (), kabın başlangıcını işaretlediğinden ve vektörümüzdeki ith öğesini silmek istiyorsak, şunları kullanabiliriz:
vec.erase(vec.begin() + index);
Eğer yakından bakarsanız, vec.begin () sadece vektörümüzün başlangıç konumuna bir işaretçi olur ve i'nin değerini ona ekleyerek işaretçiyi i konumuna yükseltir, bunun yerine işaretçiyi ith öğesine öğeye erişebiliriz:
&vec[i]
Böylece şunu yazabiliriz:
vec.erase(&vec[i]); // To delete the ith element
Sıralanmamış bir vektörünüz varsa, sıralanmamış olmasından faydalanabilir ve Dan Higgins'den CPPCON'da gördüğüm bir şeyi kullanabilirsiniz
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;
}
Liste sırası önemli olmadığından, listedeki son öğeyi alın ve kaldırmak istediğiniz öğenin üstüne kopyalayın, ardından son öğeyi pop ve silin.
iterator + indexindekste yineleyici pozisyonunu size geri verecek varsayımlara dayanmaz , bu da tüm tekrarlanabilir kaplar için geçerli değildir. Ayrıca, arka işaretçiden faydalanarak doğrusal yerine sabit karmaşıklıktır.
unordered_removeve gibi eklenmelidir gerekir unordered_remove_if... olmadıkça ve ben özledim, bu günlerde daha sık oluyor :)
std::removekabı, kaldırılacak tüm öğelerin sonunda olacak şekilde yeniden sıralar, C ++ 17 kullanıyorsanız manuel olarak böyle yapmanıza gerek yoktur.
std::removeyardımcı olur? cppreference, C ++ 17'de bile tüm removeaşırı yüklerin yüklem gerektirdiğini ve hiçbirinin bir indeks almadığını iddia ediyor .
Büyük vektörlerle (boyut> 100.000) çalışıyorsanız ve çok sayıda öğeyi silmek istiyorsanız, böyle bir şey yapmanızı tavsiye ederim:
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;
}
Kod, vec cinsinden 3'e bölünemeyen her sayıyı alır ve vec2'ye kopyalar. Daha sonra vec2'yi vec olarak kopyalar. Oldukça hızlı. 20.000.000 elementi işlemek için bu algoritma sadece 0.8 saniye sürer!
Aynı şeyi erase yöntemiyle yaptım ve çok zaman alıyor:
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)
Bir öğeyi silmek için aşağıdaki yolu kullanın:
// declaring and assigning array1
std:vector<int> array1 {0,2,3,4};
// erasing the value in the array
array1.erase(array1.begin()+n);
Daha geniş bir genel bakış için şu adresi ziyaret edebilirsiniz: http://www.cplusplus.com/reference/vector/vector/erase/
Aradığın şey olduğuna inandığım için bunu okumayı öneririm. https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom
Örneğin kullanıyorsanız
vec.erase(vec.begin() + 1, vec.begin() + 3);
vektörün n. elemanını sileceksiniz, ancak ikinci elemanı sildiğinizde, vektörün diğer tüm elemanları kaydırılacak ve vektör boyutu -1 olacaktır. Vektör boyutu () azaldığı için vektörde döngü yaparsanız bu sorun olabilir. Bu tür bir sorun varsa, standart C ++ kütüphanesinde mevcut algoritmayı kullanmanız önerilir. ve "remove" veya "remove_if".
Umarım bu yardımcı olmuştur
Önceki yanıtlar her zaman imzalı bir dizininizin olduğunu varsayar . Ne yazık ki, indeksleme ve yineleyici aritmetiği için std::vectorkullanır , bu nedenle "-Wconversion" ve arkadaşlarınız etkinse birlikte çalışmazlar. Bu, hem imzalı hem de imzasız olarak işlerken soruyu cevaplamanın başka bir yoludur:size_typedifference_type
Ayırmak:
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);
}
Almak:
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;
}
bir öğeyi vektörde değeriyle bularak silmek istiyorsanız bunu yapmanın bir yolu daha var, bunu vektörde yapmanız yeterlidir.
vector<int> ar(n);
ar.erase(remove(ar.begin(), ar.end()), (place your value here from vector array));
değerini buradan kaldıracaktır. Teşekkürler
en hızlı yol (yarışmaların zaman karmaşıklığına göre programlanması için () = sabit)
100M öğeyi 1 saniyede silebilir;
vector<int> it = (vector<int>::iterator) &vec[pos];
vec.erase(it);
ve en okunabilir yolu:
vec.erase(vec.begin() + pos);
vector<int>::iteratormutlaka aynı değildirint *