You have several ways to delete repeated numbers:
Container std :: set
std::set
is an STL container that stores a list of ordered elements without duplicates. Its use is quite simple:
std::set<int> numeros;
for( int i=0; i<10; i++ )
{
int n;
std::cout << "Introduce un número: ";
std::cin >> n;
numeros.insert(n);
}
std::cout << "Lista de números sin repeticiones:\n";
for( int numero : numeros )
std::cout << numero << '\n';
std :: vector + std :: sort + std :: unique
std::vector
is the container par excellence of the STL. It stores a list of elements without ordering, it admits duplicates and, its great advantage, all the elements are in contiguous positions of memory, reason why its access is very fast when taking advantage of the benefits of the cache.
std::sort
is an STL utility that allows you to sort a range of values.
std::unique
is a utility of the STL that given a range of elements (start and end of range iterators), eliminates all contiguous occurrences of repeated elements. Well, it does not really eliminate them ... it moves them at the end of the range. Finally, it returns an iterator to the first duplicate element.
std::vector<int> numeros;
for( int i=0; i<10; i++ )
{
int n;
std::cout << "Introduce un número: ";
std::cin >> n;
numeros.push_back(n);
}
// Primero ordenamos la secuencia
std::sort(numeros.begin(),numeros.end());
// Despues eliminamos los duplicados
numeros.erase(std::unique(numeros.begin(),numeros.end()),numeros.end());
std::cout << "Lista de números sin repeticiones:\n";
for( int numero : numeros )
std::cout << numero << '\n';
Although it may seem a more cumbersome method, this mechanism is much faster than the previous one before quite long sequences ... the longer the greater the difference in speed.
Container std :: set + std :: tie
The two previous methods have one drawback and that is that they order the initial sequence. This method is designed to keep the original sequence unaltered but without duplicates.
If you check the std::set
help you can see that the insert()
method returns a std::pair
, which is just an object that allows you to store a pair of values. The first value is an iterator to the inserted element and the second value is a Boolean that indicates whether the inserted element is new in the container or if it already existed.
std::tie
is a function that allows to exploit that object std::pair
to recover its individual elements. The great advantage of this method is that it allows us to discard values that do not interest us. For your particular case you are only interested in the second value, the Boolean: if it is true it means that the element did not exist in the container.
The idea is to combine std::set
and std::tie
to identify the duplicate elements and eliminate them without needing to reorganize the original container:
std::vector<int> entrada{ 1,2,1,6,4,2,2,2,3 };
std::vector<int> salida;
std::set<int> detector;
for( numero : entrada)
{
bool nuevo;
std::tie(std::ignore,nuevo) = detector.insert(numero);
if( nuevo )
salida.push_back(numero); // solo se añaden los numeros no duplicados
}
for( int numero : salida)
std::cout << numero << '\n';
std::ignore
is not more than a kind of wastebasket, it is used to discard values we do not need.
Programming everything from scratch
If you have a sequence and you want to eliminate the duplicates you can choose to go through the sequence from beginning to end and in each iteration compare the current element with all the previous ones ... if there is a match the element is duplicated and you must eliminate it:
std::vector<int> entrada{ 1,2,1,6,4,2,2,2,3 };
std::vector<int> salida;
for( auto it = entrada.begin(); it != entrada.end(); ++it )
{
bool duplicado = false;
for( auto it2 = entrada.begin(); it2 != it; ++it2 )
{
if( *it == *it2 )
{
duplicado = true;
break;
}
}
if( !duplicado )
salida.push_back(*it);
}
for( int numero : salida)
std::cout << numero << '\n';
Simplifying the previous example
We can also give a brief review of the previous example to take advantage of the STL:
std::vector<int> entrada{ 1,2,1,6,4,2,2,2,3 };
std::vector<int> salida;
for( auto it = entrada.begin(); it != entrada.end(); ++it )
{
if( std::count(entrada.begin(),it,*it) == 0 )
salida.push_back(*it);
}
for( int numero : salida)
std::cout << numero << '\n';
std::count
tells you the number of times a certain value repeats in a range. In this case we iterate from the beginning of the list to the number immediately before the one we are checking and the number to look for is the current number:
// (1) (2) (3)
std::count(entrada.begin(), it, *it)
// (1): inicio del rango = inicio de la lista
// (2): fin del rango = posición actual (no se incluye en la búsqueda)
// (3): valor a buscar = número actual
Greetings.