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() + 2
bir de std::list
, kullanmak zorunda std::advance
olduğ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>::iterator
a 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
erase
Yöntem iki şekilde kullanılacaktır:
Tek eleman silme:
vector.erase( vector.begin() + 3 ); // Deleting the fourth element
Eleman aralığının silinmesi:
vector.erase( vector.begin() + 3, vector.begin() + 5 ); // Deleting from fourth element to sixth element
Aslında, erase
fonksiyon 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 + index
indekste 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_remove
ve gibi eklenmelidir gerekir unordered_remove_if
... olmadıkça ve ben özledim, bu günlerde daha sık oluyor :)
std::remove
kabı, 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::remove
yardımcı olur? cppreference, C ++ 17'de bile tüm remove
aşı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::vector
kullanı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_type
difference_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>::iterator
mutlaka aynı değildirint *