C ++,count_if和equals

时间:2013-03-14 02:57:36

标签: c++ algorithm class countif

我有一个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 == ???;
}

我找到的文件leaves a lot to be desired

我觉得我错过了一些非常明显的东西,但我看不出它是什么。有谁可以指出我的错误?

杰夫

2 个答案:

答案 0 :(得分:5)

可以写一个仿函数来实现这个目标:

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"; });

答案 1 :(得分:1)

由于您的商品已排序,因此您可以比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());]

要查找每个项目出现的次数,请从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是线性)。