Hoe wis ik een element uit std::vector<> op index?

Ik heb een std::vector<int> en ik wil het n-de element verwijderen. Hoe doe ik dat?

std::vector<int> vec;
vec.push_back(6);
vec.push_back(-17);
vec.push_back(12);
vec.erase(???);

Antwoord 1, autoriteit 100%

Als u een enkel element wilt verwijderen, kunt u het volgende doen:

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()));

Of om meer dan één element tegelijk te verwijderen:

// Deletes the second through third elements (vec[1], vec[2])
vec.erase(std::next(vec.begin(), 1), std::next(vec.begin(), 3));

Antwoord 2, autoriteit 32%

De wismethode op std::vector is overbelast, dus het is waarschijnlijk duidelijker om aan te roepen

vec.erase(vec.begin() + index);

wanneer u slechts één element wilt wissen.


Antwoord 3, autoriteit 7%

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);
}

Antwoord 4, autoriteit 3%

De erasemethode wordt op twee manieren gebruikt:

  1. Eén element wissen:

    vector.erase( vector.begin() + 3 ); // Deleting the fourth element
    
  2. Bereik van elementen wissen:

    vector.erase( vector.begin() + 3, vector.begin() + 5 ); // Deleting from fourth element to sixth element
    

Antwoord 5

Eigenlijk werkt de functie erasevoor twee profielen:

  • Een enkel element verwijderen

    iterator erase (iterator position);
    
  • Een reeks elementen verwijderen

    iterator erase (iterator first, iterator last);
    

Sinds std::vec.begin() het begin van de container markeert en als we het ith-element in onze vector willen verwijderen, kunnen we het volgende gebruiken:

vec.erase(vec.begin() + index);

Als je goed kijkt, is vec.begin() slechts een aanwijzer naar de startpositie van onze vector en het toevoegen van de waarde van i eraan verhoogt de aanwijzer naar de i-positie, dus in plaats daarvan hebben we toegang tot de aanwijzer naar het ith-element door:

&vec[i]

Dus we kunnen schrijven:

vec.erase(&vec[i]); // To delete the ith element

Antwoord 6

Als je een ongeordende vector hebt, kun je profiteren van het feit dat deze ongeordend is en iets gebruiken dat ik van Dan Higgins op CPPCON heb gezien

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;
}

Aangezien de volgorde van de lijst er niet toe doet, neemt u gewoon het laatste element in de lijst en kopieert u dit over het item dat u wilt verwijderen, en verwijdert u het laatste item.


Antwoord 7

Het lijkt misschien voor de hand liggend voor sommige mensen, maar om de bovenstaande antwoorden nader toe te lichten:

Als u std::vector-elementen verwijdert met behulp van erasein een lus over de hele vector, moet u uw vector in omgekeerde volgorde, dat wil zeggen met behulp van

for (int i = v.size() - 1; i >= 0; i--)

in plaats van (de klassieke)

for (int i = 0; i < v.size(); i++)

De reden is dat indexen worden beïnvloed door erase, dus als u het vierde element verwijdert, is het voormalige vijfde element nu het nieuwe vierde element, en dat gebeurt niet worden verwerkt door uw lus als u i++doet.

Hieronder is een eenvoudig voorbeeld dat dit illustreert waarbij ik alle odds-elementen van een int-vector wil verwijderen;

#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;
}

Uitvoer:

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 # # # # #

Merk op dat in de tweede versie met toenemende indices, even getallen niet worden weergegeven omdat ze worden overgeslagen vanwege i++


Antwoord 8

Wis een element met index :

vec.erase(vec.begin() + index);

Wis een element met waarde:

vec.erase(find(vec.begin(),vec.end(),value));

Antwoord 9

Als je met grote vectoren werkt (grootte > 100.000) en veel elementen wilt verwijderen, raad ik aan om zoiets als dit te doen:

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;
}

De code neemt elk getal in vec dat niet door 3 kan worden gedeeld en kopieert het naar vec2. Daarna kopieert het vec2 in vec. Het is behoorlijk snel. Om 20.000.000 elementen te verwerken duurt dit algoritme slechts 0,8 sec!

Ik deed hetzelfde met de wismethode, en het kost heel veel tijd:

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)

Antwoord 10

Gebruik de volgende manier om een element te verwijderen:

// declaring and assigning array1 
std:vector<int> array1 {0,2,3,4};
// erasing the value in the array
array1.erase(array1.begin()+n);

Voor een meer algemeen overzichtkunt u terecht op: http://www.cplusplus.com/reference/vector/vector/erase/


Antwoord 11

Ik raad aan om dit te lezen omdat ik denk dat je dat zoekt.https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom

Als u bijvoorbeeld

. gebruikt

vec.erase(vec.begin() + 1, vec.begin() + 3);

je wist het n -de element van de vector, maar als je het tweede element wist, worden alle andere elementen van de vector verschoven en is de grootte van de vector -1. Dit kan een probleem zijn als u door vector loopt, aangezien vector size() kleiner wordt. Als je een probleem hebt zoals dit, wordt een link voorgesteld om het bestaande algoritme in de standaard C++ -bibliotheek te gebruiken. en “remove” of “remove_if”.

Ik hoop dat dit heeft geholpen


Antwoord 12

De vorige antwoorden gaan ervan uit dat je altijdeen ondertekende index hebt. Helaas gebruikt std::vectorsize_typevoor indexering, en difference_typevoor iteratorberekeningen, dus ze werken niet samen als je “- Wconversion” en vrienden ingeschakeld. Dit is een andere manier om de vraag te beantwoorden, terwijl je zowel ondertekende als niet-ondertekende kunt behandelen:

Om te verwijderen:

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);
}

Om mee te nemen:

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;
}

Antwoord 13

hier is nog een manier om dit te doen als u een element wilt verwijderen door dit met zijn waarde in vector te vinden, u hoeft dit alleen op vector te doen.

vector<int> ar(n);
ar.erase(remove(ar.begin(), ar.end()), (place your value here from vector array));

Het verwijdert uw waarde vanaf hier.
bedankt


Antwoord 14

Hoe zit het?

void squeeze(vector<int> &v)
{
    int j = 0;
    for (int i = 1; i < v.size(); i++)
        if (v[i] != v[j] && ++j != i)
            v[j] = v[i];
    v.resize(j + 1);
}

Antwoord 15

Als u een element in een for-lus wilt wissen, doet u het volgende:

for(int i = 0; i < vec.size(); i++){
    if(condition)
        vec.erase(vec.begin() + i);
}

Antwoord 16

de snelste manier (voor programmeerwedstrijden op tijdcomplexiteit () = constant)

kan 100m item in 1 seconde wissen;

   vector<int> it = (vector<int>::iterator) &vec[pos];
    vec.erase(it);

en de meest leesbare manier:
vec.erase(vec.begin() + pos);

Other episodes