Удаление элементов по индексу в векторных парах


У меня есть векторные пары целых чисел как на первой, так и на второй позиции, и вход довольно специфичен.
Во-первых, у меня есть входы i, которые все идут в первые точки вектора, но затем появляется второй массив входов, который должен идти во вторую позицию.
Однако, что я хотел бы сделать, у меня есть условие, что если я найду вход второго пятна больше, чем определенное значение (mana, в моем случае переменная), я хотел бы просто не помещать его в векторную пару, и удалите первый элемент этого индекса из первой позиции, и у меня возникли проблемы с тем, как его закодировать. Вот часть этого кода:

vector<pair<int, int>>spellOne;

for (int i = 0; i < nSpellOne; i++)
{
    scanf_s("%d", &input);
    spellOne.back().first = input;
}

for (int i = 0; i < nSpellOne; i++)
{
    scanf_s("%d", &input);

    if (input > mana)
    {
        // removing the element on .first position at i index
    }
    else
    {
        spellOne.at(i).second = input;
    }
}

Может ли кто-нибудь помочь мне, как это сделать, и если это вообще возможно, или я должен переключиться на другой тип массивов? Я также рассматривал возможность использования карт, но это было невозможно, так как есть большая вероятность, что я получу одно и то же значение дважды в любом первом/втором месте вектора, поэтому я не могу использовать их в качестве ключа.

2 3

2 ответа:

Я привел пример,который должен помочь вам выполнить вашу задачу. В моем примере ниже я заполняю вектор, а затем стираю пары, у которых второе значение больше определенного порога (в данном случае 2).

Теперь вы можете использовать две переменные, чтобы отслеживать цикл, который стирает элементы, один цикл через весь вектор и один, чтобы отслеживать текущий индекс, подлежащий проверке; если мы удаляем v[3], то следующий элемент v[4] сдвигается (потому что мы вызвали erase()) в место v[3], таким образом, мы должны снова рассмотреть индекс 3!
#include <iostream>
#include <utility>
#include <vector>

using namespace std;


int main()
{
    vector< pair<int, int> > v;
    int N = 5;
    const int threshold = 2;
    for(int i = 0; i < N; ++i)
        v.push_back(make_pair(i, i));

    int i = 0;
    while(i < v.size())
        if (v[i].second > threshold)
            v.erase(v.begin() + i);
        else
            i++;

    for(int i = 0; i < v.size(); ++i)
        cout << "(" << v[i].first << ", " << v[i].second << ")\n";

    cout << "Done" << endl;
}

Вывод:

(0, 0)
(1, 1)
(2, 2)
Done

Правка для вашего комментария: вы можете попробовать это:

int i = 0;
while(i < nSpellOne.size())
{
    scanf_s("%d", &input);
    if (input > mana)
        nSpellOne.erase(nSpellOne.begin() + i);
    else
        i++;
}

PS-при написании эффективного кода не беспокойтесь о том, является ли std::cin или scanf() быстрее, сосредоточьтесь на своем алгоритме!

Во-первых, ваш код для загрузки вектора не совсем корректен.

vector<pair<int, int>>spellOne;

for (int i = 0; i < nSpellOne; i++)
{
    int input1, input2;
    //scanf is C! Prefer C++ for doing input
    if(std::cin >> input1 >> input2)
        //Simply calling .back() presumes that an element already exists there, which in
        //the code you've provided, this isn't the case. emplace_back will allocate the 
        //memory correctly.
        spellOne.emplace_back(input1, input2);
    else
        break;//Could also do error handling here
}

std::vector's не просто волшебным образом имеет пространство для любых элементов, которые вы запрашиваете: вы должны специально использовать методы, которые вставляют элементы в вектор, будь то emplace_back (идеально), emplace, push_back, или insert. back запрашивает только самый задний элемент и будет иметь плохие результаты, если рассматриваемый элемент не существует, или если вы ожидаете, что он вернет уникальный элемент. вызов.

Тогда при итерации по вектору правильное использование STL значительно упростит дело.

auto it = std::remove_if(
    spellOne.begin(),
    spellOne.end(),
    [mana](std::pair<int, int> const& data) {
        if(data.second > mana) return true;
        else return false;
    }
);

spellOne.erase(it, spellOne.end());

Этот код вносит небольшое изменение в ваш вариант использования, где мы вводим второй номер одновременно с первым номером. Таким образом, вход в эту программу будет 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10. Если вам действительно нужен ваш предыдущий заказ (хотя я не рекомендую его), этот код будет работать нормально, хотя и будет медленнее.

vector<pair<int, int>>spellOne;

for (int i = 0; i < nSpellOne; i++)
{
    int input;
    if(std::cin >> input)
        spellOne.emplace_back(input, 0);
    else
        break;
}

for(std::pair<int, int> & data : spellOne) {
    int input;
    if(std::cin >> input)
        data.second = input;
    else
        break;
}

auto it = std::remove_if(
    spellOne.begin(),
    spellOne.end(),
    [mana](std::pair<int, int> const& data) {
        if(data.second > mana) return true;
        else return false;
    }
);

spellOne.erase(it, spellOne.end());