ALGO25 / BLOG

unique și erase: eliminarea duplicatelor în C++

Înțelege ce elimină unique și de ce dimensiunea vectorului rămâne aceeași până la erase. Separă duplicatele consecutive de repetările oriunde în șir.

std::unique compactează o secvență astfel încât fiecare grup de elemente consecutive echivalente să păstreze o singură apariție. Nu micșorează singur dimensiunea vectorului și nu elimină automat toate repetările aflate în poziții separate.

Duplicate consecutive înseamnă vecine

Pentru 2 2 3 2, prefixul rezultat după unique este 2 3 2. Ultimul 2 rămâne deoarece nu era în același grup consecutiv cu primele două valori. Dacă vrei fiecare valoare o singură dată indiferent de poziție, trebuie să alegi și o strategie pentru această cerință.

Sortarea înainte de unique aduce valorile egale una lângă alta, dar schimbă ordinea inițială. Dacă enunțul cere păstrarea ordinii primei apariții, sortarea nu este automat acceptabilă. Verifică cerința înainte să aplici o combinație memorată.

Rezultatul este un nou sfârșit logic

Funcția întoarce iteratorul de după prefixul compactat. Elementele de la început până la acel iterator reprezintă rezultatul util. Zona rămasă după el nu trebuie interpretată ca parte a rezultatului algoritmului.

Într-un vector, size rămâne neschimbat după unique. Pentru a elimina fizic coada din secvența logică a containerului, folosești erase pe intervalul dintre noul sfârșit și vechiul end. Abia această operație micșorează numărul elementelor vectorului.

Pentru 2,2,3,2, unique produce prefixul util 2,3,2. Dimensiunea vectorului rămâne 4 până când erase elimină coada de după noul sfârșit.Pentru 2,2,3,2, unique produce prefixul util 2,3,2. Dimensiunea vectorului rămâne 4 până când erase elimină coada de după noul sfârșit.Mărește schema ↗

Echivalentul pe un tablou clasic

Într-un tablou cu capacitate fixă, compactarea schimbă prefixul util, iar programul actualizează dimensiunea logică. Capacitatea rezervată nu trebuie să se micșoreze pentru ca rezultatul să fie corect. La afișare și prelucrare folosești noua dimensiune, nu capacitatea.

Aceeași distincție explică de ce afișarea întregului vector imediat după unique poate produce valori care par ciudate: afișezi și zona care nu mai aparține rezultatului util, deși încă aparține containerului până la erase.

Verifică semantica înainte de cod

Testează toate valorile egale, nicio pereche vecină egală și aceeași valoare în două grupuri separate. Pentru 5 5 5, prefixul util are un singur 5. Pentru 5 7 5, unique singur păstrează toate cele trei elemente.

Dacă folosești o regulă personalizată de echivalență, aceasta trebuie să fie coerentă. Nu confunda echivalența pentru grupare cu ordinea strictă cerută de un comparator de sortare: răspund la întrebări diferite despre perechi de elemente.

Continuă cu compactarea și ștergerea, iteratorii și sortările.

Întrebări frecvente

Ce elimină std::unique?

Compactează grupurile de elemente consecutive echivalente, păstrând câte un reprezentant. Pentru 2 2 3 2, prefixul rezultat este 2 3 2, deoarece ultimul 2 aparține altui grup.

De ce size nu scade după unique pe un vector?

unique întoarce noul sfârșit logic, dar nu schimbă singur dimensiunea containerului. Elimină intervalul dintre acel iterator și sfârșitul vechi pentru a scurta efectiv vectorul.

Trebuie să sortez înainte de unique?

Dacă vrei o singură apariție pentru fiecare valoare indiferent de poziție, sortarea grupează duplicatele. Ea schimbă însă ordinea; dacă ordinea inițială contează, ai nevoie de altă strategie.