How to find and count different duplicates in a container

Jul 5, 2015 at 9:08pm
Hi guys. I've been reading about ways of finding duplicates in a container, but I still lost of how to solve my problem which is how can I count the different number of duplicates in a vector<int> container.

Let's imagine I have the following container: { 1, 1, 1, 3, 3, 3, 3, 8, 8 ... } How can I count and if possible, put the count result in a variable? for example a = 3 (because of three 1's), b = 4, c = 2.

Thank you for the help.
Jul 5, 2015 at 9:44pm
What exactly you want to do? Maintaing a relation like "this sequence contains 3 1's, 4 3's and 2 8's"? Something else?
Is your sequence always sorted? Can you change your sequence?
Jul 5, 2015 at 10:15pm
Yes, the sequence is always sorted. I need to know how many of each duplicates exist in a container, thats all, because I'll use this information (the quantity of each number) after. I don't need to change anything in the container.
Jul 5, 2015 at 10:26pm
Using vectors and algorithms:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <algorithm>
#include <iostream>
#include <iterator>
#include <utility>
#include <vector>

int main()
{
    std::vector<int> data {1, 1, 1, 3, 3, 3, 3, 8, 8};
    std::vector<int> unique;
    //http://en.cppreference.com/w/cpp/algorithm/unique_copy
    std::unique_copy(data.begin(), data.end(), std::back_inserter(unique));

    std::vector<std::pair<int, int>> frequency;
    for(int i: unique)
        //http://en.cppreference.com/w/cpp/algorithm/count
        frequency.emplace_back(i, std::count(data.begin(), data.end(), i));

    for(const auto& e: frequency)
        std::cout << "Element " << e.first << " encountered " << e.second << " times\n";
}
http://coliru.stacked-crooked.com/a/febe9e3fc832bd30

Using map:
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <map>
#include <vector>

int main()
{
    std::vector<int> data {1, 1, 1, 3, 3, 3, 3, 8, 8};
    std::map<int, int> frequency;
    for(int i: data)
        ++frequency[i];
    for(const auto& e: frequency)
        std::cout << "Element " << e.first << " encountered " << e.second << " times\n";
}
http://coliru.stacked-crooked.com/a/c4153b0b631edde2

Jul 5, 2015 at 10:44pm
First of all, thank you very much for this help. I understood almost everything on your code, except this part:

1
2
for(const auto& e: frequency)
        std::cout << "Element " << e.first << " encountered " << e.second << " times\n";


What if I have, 500 different ints? e.first and e.second will show all of then? or just two of then? And how can I access the information of how many times each number exists? (i.e.: Element 1 encounter 3 times)
Last edited on Jul 5, 2015 at 10:46pm
Jul 5, 2015 at 10:49pm
This is a range-for loop.
On each iteration e is assigned a value from container.
That value ib both cases is std::pair: a structure which contains two values named first and second.
In both cases this pair denotes a frequency entry: first member says which number and second says how many times it is encountered.

So, this loop will show all possible unique elements and their frequency.
Jul 5, 2015 at 10:58pm
Oh, I get it now. Thank you. Just one more question, for-ranged loops are not allowed in C++98. Can I change this to:
1
2
for (int i = 0; int < frequency.size(); i++) 
                std::cout << "Element " << e.first << " encountered " << e.second << " times\n";
?


Last edited on Jul 5, 2015 at 10:58pm
Jul 5, 2015 at 11:04pm
YOu can for vector-based program, but you will need to properly address elements through index.

For map one, you will need to use iterator-based approach (I would recommend it for vector one too)

1
2
for (std::map<int, int>::const_iterator it = frequency.begin(); it != frequency.end(); ++it) 
    std::cout << "Element " << it->first << " encountered " << it->second << " times\n";
Jul 5, 2015 at 11:09pm
Do you mean the vector based or the map-based iteration?
http://www.cplusplus.com/reference/vector/vector/begin/
http://www.cplusplus.com/reference/map/map/begin/

Or the array dereferencing style with the vector?
http://www.cplusplus.com/reference/vector/vector/operator%5B%5D/

(The vector documentation examples do not have a vector of pairs, but mere vector of ints. Adapt.)
Jul 5, 2015 at 11:18pm
I have a vector based vector. I created this vector using the .push_back() function. So, I have a 1D array vector (with ints), And I can use the array deference style to access its elements, right? Now, I need to know how many times each element is repeated.
Jul 5, 2015 at 11:25pm
MiiNiPaa's vector-based example has std::vector<std::pair<int, int>> frequency;
Therefore, printing the pairs:
1
2
for (std::vector<std::pair<int, int>>::const_iterator it = frequency.begin(); it != frequency.end(); ++it) 
    std::cout << "Element " << it->first << " encountered " << it->second << " times\n";
Jul 5, 2015 at 11:27pm
But how can I assign values of a vector<int> to a vector<std::pair<int, int>> ?
Jul 6, 2015 at 7:03am
Look again at MiiNiPaa's "Using vectors and algorithms" program.

It does use C++11 vector::emplace_back(), but you can use C++98 vector::push_back().
With both those methods I do recommend adding
frequency.reserve( unique.size() );
before the counting-loop. That avoids unnecessary reallocations.
Jul 6, 2015 at 11:53am
I get it now. Thank you MiiNiPaa and keskiverto for the help and for taking my doubts off.
Topic archived. No new replies allowed.