[英]C++, count_if, and equals
我有一个带有名称和数字的struct
:
struct S {
string name;
int number;
};
S
对象存储在向量中。 向量根据name
排序。 可能有多个具有相同name
。
当遍历向量中的项目时,我尝试使用count_if
来检测重复项:
for(size_t i = 0; i < v.size(); ++i)
{
const S& s = v[i];
int count = count_if(v.begin(), v.end(), XXX);
// do something with count
}
在上面,我不知道XXX应该是什么。 我试图创建一个谓词,但是它没有任何可比较的意义,因为它没有用:
bool IsEqualName(const S& s) {
return s.name == ???;
}
我要查找的文档还有很多不足之处 。
我感觉好像缺少了很明显的东西,但是我看不到它是什么。 谁能指出我的错误?
杰夫
可以编写一个仿函数来实现此目的:
struct FindName
{
FindName(const std::string& name) : name_(name) {}
bool operator()(const S& s) { return s.name == name_; }
private:
std::string name_;
};
int count = count_if(v.begin(), v.end(), FindName("noloader"));
如果您使用的是C ++ 11,请使用lambda:
int count = count_if(v.begin(), v.end(),
[](const S& s){ return s.name == "noloader"; });
由于您的项目已排序,因此您可以比find_if做得更好。 在这种情况下, std::upper_bound
应该可以正常工作。
由于您将S
的顺序基于name
因此最可能最简单的方法是重载operator<
来做到这一点:
struct S {
string name;
int number;
bool operator<(S const &other) { return name < other.name; }
};
[顺便说一下,您可以在sort(v.begin(), v.end());
时使用它,例如sort(v.begin(), v.end());
]
要查找每个项目出现的次数,请从v.begin()开始,然后使用std::upper_bound
查找等于第一个项目的上限,然后将要查看的范围的开头更新为迭代器upper_bound
刚刚返回,并重复直到到达集合的末尾:
std::vector<size_t> counts;
auto pos = v.begin();
for (auto prev=v.begin(); prev != v.end(); prev = pos) {
pos = std::upper_bound(prev, v.end(), *prev);
counts.push_back(pos - prev);
}
如果您有很多重复项,那么这至少有可能会更快一些;如果您确实有很多重复项,那么这可能会快得多( upper_bound
是对数的,而find_if
是线性的)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.