Since your items are sorted, you can do better than find_if. In this case, std::upper_bound
should work nicely.
Since you're basing the order of your S
on name
it's probably easiest to start by overloading operator<
to do that:
struct S {
string name;
int number;
bool operator<(S const &other) { return name < other.name; }
};
[By the way, you can use that when sorting, as in sort(v.begin(), v.end());
]
To find how many times each item occurs, start from v.begin(), and use std::upper_bound
to find the upper bound of items equal to the first, then update the beginning of the range you're looking at to the iterator upper_bound
just returned, and repeat until you reach the end of the collection:
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);
}
This has at least the potential to be somewhat faster if you have quite a few duplicates -- or a lot faster if you really have a lot of duplicates (upper_bound
is logarithmic, where find_if
is linear).