如果项目ID与参数匹配,我试图编写一个算法来搜索并从项目向量中删除项目。请参阅下面的示例代码:
struct item{
item(int newID){id = newID;}
bool operator==(const item& other){return id = other.id;}
int id
};
std::vector<std::unique_ptr<item>> vec;
vec.push_back(std::unique_ptr<item>(new item(10));
vec.push_back(std::unique_ptr<item>(new item(15));
vec.push_back(std::unique_ptr<item>(new item(20));
所以,使用上面的代码,我希望能够搜索存储值15的项目,并将其从向量中删除,删除它。
我将如何做到这一点?
不可否认,我可能也需要使用独特的指针,所以如果我的语法不正确,请随时纠正我。
我尝试过的一些解决方案如下:
void remove_item(int id){
vec.erase(
std::remove_if(
vec.begin(),
vec.end(),
[](const item& e){
return id==e.id;
}),
vec.end()
);
上面的代码产生一个错误,指出变量id不是lambda表达式的捕获列表的一部分。
其次,我尝试过:
void remove_item(item e){
auto iter = std::find(vec.begin(), vec.end(), e);
vec.erase(iter);
}
在这种情况下,上面的代码会在==运算符成员函数中产生类型不匹配错误。
答案 0 :(得分:3)
您需要将id
添加到lambda的捕获列表中,以便它可以访问它。然后你需要将传递给lambda的类型设为*vec.begin()
的类型std::unique_ptr<item>
而不是item
void remove_item(int id){
vec.erase(
std::remove_if(
vec.begin(),
vec.end(),
[id](const std::unique_ptr<item>& e){
return id==e->id;
}),
vec.end()
);
}
从您的代码中删除所有其他无关的错误,您将拥有类似的内容:
struct item {
item(int newID) { id = newID; }
bool operator==(const item& other) { return id == other.id; } // == here not =
int id;
};
std::vector<std::unique_ptr<item>> vec;
void remove_item(int id) {
vec.erase(std::remove_if(
vec.begin(), vec.end(), [id](const std::unique_ptr<item>& e)
{ return id == e->id; })
,vec.end());
}
int main()
{
vec.push_back(std::unique_ptr<item>(new item(10))); // was missing a close paren
vec.push_back(std::unique_ptr<item>(new item(15))); // was missing a close paren
vec.push_back(std::unique_ptr<item>(new item(20))); // was missing a close paren
remove_item(15);
for (const auto & e : vec)
std::cout << e->id << " ";
}
答案 1 :(得分:2)
使用删除 - 删除习语:
// search for this value
const int val = 15;
// use lambda capture to get "val" into lambda
auto lambda = [val] (const std::unique_ptr<item> & a) { return a->id == val;};
// use remove-erase idiom
auto rem = std::remove_if(vec.begin(), vec.end(), lambda);
vec.erase(rem, vec.end());
答案 2 :(得分:0)
正如Fred Larson所说,你应该使用“erase remove_if”这个成语。 例如:
std::vector<std::unique_ptr<item>> vec;
vec.push_back(std::make_unique<item>(10));
vec.push_back(std::make_unique<item>(15));
vec.push_back(std::make_unique<item>(20));
vec.erase(std::remove_if(vec.begin(), vec.end(),
[](std::unique_ptr<item> const& item) -> bool { return item->id > 10; }), vec.end());
std::cout << vec.size(); // Output will be 1
答案 3 :(得分:0)
首先,我想说的是,而不是使用push_back
&amp; insert
,更喜欢emplace_back
&amp; emplace
C++ containers
。我之所以这样说是因为而不是这样写: -
vector<unique_ptr<item>> v;
v.push_back(unique_ptr<item>(new item(5));
您可以这样做: -
vector<unique_ptr<item>> v;
v.emplace_back(new item(5));
其次,您需要知道是否要删除值15的“一个项目”或“所有项目”。这是因为对于前者,您需要使用find_if
而对于第二种情况,您应该使用remove_if
。您也可以在第一种情况下使用remove_if
(但在第二种情况下不使用find_if
)但是不建议使用remove_if
移位第一种情况下不需要的元素案件。加号find_if
只是将迭代器返回到条件首次匹配的项目。因此,选择是你的和明智地使用它。
代码如下: -
// find_if
#include <iostream>
#include <memory>
#include <vector>
#include <algorithm>
using namespace std;
struct item
{
int x;
item(){}
item(int x)
{
this->x=x;
}
};
int main()
{
vector<unique_ptr<item>> v;
v.emplace_back(new item(15));
v.emplace_back(new item(5));
v.emplace_back(new item(7));
v.emplace_back(new item(15));
v.emplace_back(new item(27));
v.emplace_back(new item(15));
v.emplace_back(new item(80));
cout<<"deleting the item storing value 15...\n";
auto itr = find_if(v.begin(), v.end(), [](unique_ptr<item> &u) // you cant copy two `unique_ptr` as they can always be `moved & not copied`, hence we are `passing them by reference`
{
return (u->x==15);
});
v.erase(itr); // as you need to remove only one item so specify the `iterator` pointing to the required item in `erase`
for (auto &u:v) see the use of `reference` again as without it the compiler throws error messages
{
cout<<u->x<<" ";
}
return 0;
}
输出将是: -
deleting the item storing value 15...
5 7 15 27 15 80
对于remove_if
,您只需要进行以下修改: -
auto itr = remove_if(v.begin(), v.end(), [](unique_ptr<item> &u)
{
return (u->x==15);
});
v.erase(itr,v.end()); // as you need to delete a range of items so you need to specify a range (here `itr` to `v.end()`) in `erase`
此处的输出将为: -
deleting the items storing value 15...
5 7 27 80
现在我想你的怀疑会得到很好的清理!!!