【发布时间】:2010-06-22 14:39:49
【问题描述】:
假设我有以下两种数据结构:
std::vector<int> all_items;
std::set<int> bad_items;
all_items 向量包含所有已知项目,bad_items 向量包含一个坏项目列表。这两种数据结构完全相互独立地填充。
编写一个返回std::vector<int> 的方法的正确方法是什么,该方法包含all_items 的所有元素,而不是bad_items?
目前,我有一个笨拙的解决方案,我认为可以更简洁地完成。我缺乏对 STL 函数适配器的理解。因此问题。我目前的解决方案是:
struct is_item_bad {
std::set<int> const* bad_items;
bool operator() (int const i) const {
return bad_items.count(i) > 0;
}
};
std::vector<int> items() const {
is_item_bad iib = { &bad_items; };
std::vector<int> good_items(all_items.size());
std::remove_copy_if(all_items.begin(), all_items.end(),
good_items.begin(), is_item_bad);
return good_items;
}
假设all_items、bad_items、is_item_bad 和items() 都是某些包含类的一部分。有没有办法写items() getter 这样:
- 方法中不需要临时变量?
- 不需要自定义函子
struct is_item_bad?
我曾希望只使用std::set 上的count 方法作为函子,但我无法用remove_copy_if 算法预测正确的表达方式。
编辑: 修复了items() 中的逻辑错误。实际代码没有问题,是转录错误。
编辑:我接受了一个不使用std::set_difference 的解决方案,因为它更通用,即使std::vector 未排序也可以工作。我选择在我的代码中使用 C++0x lambda 表达式语法。我的最终items() 方法如下所示:
std::vector<int> items() const {
std::vector<int> good_items;
good_items.reserve(all_items.size());
std::remove_copy_if(all_items.begin(), all_items.end(),
std::back_inserter(good_items),
[&bad_items] (int const i) {
return bad_items.count(i) == 1;
});
}
在大约 800 万个项目的向量上,上述方法在 3.1 秒内运行。我在工作台上标记了std::set_difference 方法,它运行了大约 2.1 秒。感谢所有提供出色答案的人。
【问题讨论】:
-
也许你可以使用std::set_difference? cplusplus.com/reference/algorithm/set_difference
-
如果您没有重复的对象,您可以为此使用两个集合和集合操作。但我猜你需要一个向量。