Vediamo un caso ingannevole in C++, in pratica si coinvolge l'uso del container std::vector e la funzione std::unique per rimuovere elementi duplicati da un vettore.
Importante ricordare che la funzione std::unique non rimuove tutti gli elementi duplicati dal vettore ma li sposta verso la fine di esso e restituisce un iteratore che indica la nuova dimensione "logica" del vettore (senza i duplicati). Quindi bisogna usare il metodo erase per eliminare effettivamente gli elementi in più.
Per esempio:
#include <iostream>
#include <algorithm>
#include <vector>
int main() {
std::vector<int> numbers = {1, 2, 2, 3, 3, 3, 4, 4, 5};
auto newEnd = std::unique(numbers.begin(), numbers.end());
numbers.erase(newEnd, numbers.end());
for (int num : numbers) {
std::cout << num << " ";
}
return 0;
}
Dirai che l'output sia 1 2 3 4 5, ma in realtà potrebbe essere qualsiasi cosa a causa dei valori rimanenti nel vettore dopo std::unique semplicemente perché non garantisce l'ordine degli elementi rimasti ma solo la rimozione dei duplicati consecutivi.
In sostanza devi assicurarti di utilizzare erase per togliere gli elementi in più dopo aver usato std::unique.
Vediamo un esempio più articolato!
#include <iostream>
#include <algorithm>
#include <vector>
int main() {
std::vector<int> numbers = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5};
std::cout << "Vector prima dell'eliminazione dei duplicati:" << std::endl;
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
std::sort(numbers.begin(), numbers.end());
auto newEnd = std::unique(numbers.begin(), numbers.end());
numbers.erase(newEnd, numbers.end());
std::cout << "Vector dopo l'eliminazione dei duplicati:" << std::endl;
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
Come potete vedere l'output parla chiaro i duplicati consecutivi sono stati tolti ma l'ordine degli elementi non è quello che ci si aspetterebbe dalla sequenza originale, con erase viene risolto il problema!