按向量对中的索引删除元素
Removing elements by index in vector pairs
我在第一个和第二个位置都有整数向量对,输入非常具体。
首先,我有 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;
}
}
任何人都可以帮助我了解如何做到这一点,如果可能的话,或者我应该切换到不同类型的数组吗?
我也考虑过使用地图,但那是不可能的,因为我很有可能在向量中的任一 first/second 点两次获得相同的值,因此我不能将它们中的任何一个用作键。
我举了一个例子,应该可以激励你完成你的任务。在下面的示例中,我填充了向量,然后擦除第二个值大于特定阈值(在本例中为 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
不只是神奇地为您查询的任何元素提供 space:您必须专门使用将元素插入向量的方法,无论它是 emplace_back
(理想值)、emplace
、push_back
或 insert
。 back
仅请求 back-most 元素,如果所讨论的元素不存在,或者如果您希望它在每次调用时 return 一个唯一元素,则会产生不良结果。
然后,在遍历向量时,正确使用 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());
我在第一个和第二个位置都有整数向量对,输入非常具体。
首先,我有 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;
}
}
任何人都可以帮助我了解如何做到这一点,如果可能的话,或者我应该切换到不同类型的数组吗? 我也考虑过使用地图,但那是不可能的,因为我很有可能在向量中的任一 first/second 点两次获得相同的值,因此我不能将它们中的任何一个用作键。
我举了一个例子,应该可以激励你完成你的任务。在下面的示例中,我填充了向量,然后擦除第二个值大于特定阈值(在本例中为 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
不只是神奇地为您查询的任何元素提供 space:您必须专门使用将元素插入向量的方法,无论它是 emplace_back
(理想值)、emplace
、push_back
或 insert
。 back
仅请求 back-most 元素,如果所讨论的元素不存在,或者如果您希望它在每次调用时 return 一个唯一元素,则会产生不良结果。
然后,在遍历向量时,正确使用 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());