2012-02-11 8 views
9

que tienen un vector de cadenas:duplicados retirar en un vector de cadenas

std::vector<std::string> fName 

que contiene una lista de nombres de archivo <a,b,c,d,a,e,e,d,b>.

Quiero deshacerme de todos los archivos que tienen duplicados y quiero retener solo los archivos que no tienen duplicados en el vector.

for(size_t l = 0; l < fName.size(); l++) 
{ 
    strFile = fName.at(l); 
    for(size_t k = 1; k < fName.size(); k++) 
    { 
     strFile2 = fName.at(k); 
     if(strFile.compare(strFile2) == 0) 
     { 
      fName.erase(fName.begin() + l); 
      fName.erase(fName.begin() + k); 
     } 
    } 
} 

Esta es la eliminación de algunas de las duplicado, pero todavía tiene algunos duplicados izquierda, necesitan ayuda en la depuración.

También mi entrada se ve como <a,b,c,d,e,e,d,c,a> y mi salida esperada es <b> ya que todos los demás archivos b, c, d, e tienen duplicados, se eliminan.

+0

¿Desea conservar una copia de los duplicados? Es decir. ¿Quieres , o simplemente ? –

+0

No quiero conservar la copia de Dupilcates. –

Respuesta

11
#include <algorithm> 

template <typename T> 
void remove_duplicates(std::vector<T>& vec) 
{ 
    std::sort(vec.begin(), vec.end()); 
    vec.erase(std::unique(vec.begin(), vec.end()), vec.end()); 
} 

Nota: esto requiere que T tiene operator< y operator== definido.

¿Por qué funciona?

std::sort Ordenar los elementos que utilizan su operador menor que la comparación

std::unique elimina los elementos duplicados consecutivos, comparándolos con el uso de su operador de igual comparación

¿Qué pasa si quiero sólo los elementos únicos?

Entonces es mejor que el uso std :: mapa

#include <algorithm> 
#include <map> 

template <typename T> 
void unique_elements(std::vector<T>& vec) 
{ 
    std::map<T, int> m; 
    for(auto p : vec) ++m[p]; 
    vec.erase(transform_if(m.begin(), m.end(), vec.begin(), 
         [](std::pair<T,int> const& p) {return p.first;}, 
         [](std::pair<T,int> const& p) {return p.second==1;}), 
      vec.end()); 
} 

Ver: here.

+0

También es necesario incluir #include para que std :: sort y std :: unique funcionen. –

+0

Gracias Gigi esto funcionó pero no resolvió mi problema original ... Empecé con Quiero que mi salida sea y no

+0

Lo siento, quiero que mi salida sea , que no se repite. –

3

Si entiendo sus requisitos correctamente, y no estoy del todo seguro de que lo haga. ¿Desea mantener solo los elementos en su vector de los cuales no repite, corrige?

Haz un mapa de cadenas para enteros, utilizado para contar las ocurrencias de cada cuerda. Borre el vector, luego copie de vuelta solo las cadenas que solo ocurrieron una vez.

map<string,int> m; 
for (auto & i : v) 
    m[i]++; 
v.clear(); 
for (auto & i : m) 
    if(i.second == 1) 
     v.push_back(i.first); 

O, para la característica compilador desafiados:

map<string,int> m; 
for (vector<string>::iterator i=v.begin(); i!=v.end(); ++i) 
    m[*i]++; 
v.clear(); 
for (map<string,int>::iterator i=m.begin(); i!=m.end(); ++i) 
    if (i->second == 1) 
     v.push_back(i->first); 
2
#include <algorithms> 

template <typename T> 
remove_duplicates(std::vector<T>& vec) 
{ 
    std::vector<T> tvec; 
    uint32_t size = vec.size(); 
    for (uint32_t i; i < size; i++) { 
    if (std::find(vec.begin() + i + 1, vec.end(), vec[i]) == vector.end()) { 
     tvec.push_back(t); 
    } else { 
     vec.push_back(t); 
    } 
    vec = tvec; // :) 
    } 
} 
+0

claramente esto no es eficiente – perreal

+1

' std :: vector' no tiene 'pop_front()' –

+0

solo hay pop_back() no pudo encontrar un pop_front(). El Sr. Lindley sería genial si pudieras ayudar. Gracias perreal –

0

puede eliminar duplicados en O tiempo de ejecución y O (n) el espacio (log n):

std::set<std::string> const uniques(vec.begin(), vec.end()); 
vec.assign(uniques.begin(), uniques.end()); 

Pero el tiempo de ejecución O (log n) es un poco engañoso, porque el espacio O (n) realmente hace O (n) asignaciones dinámicas, que son caros en términos de velocidad. Los elementos también deben ser comparables (aquí con operator<(), que std::string admite como comparación lexicográfica).

Si desea almacenar sólo los elementos singulares:

template<typename In> 
In find_unique(In first, In last) 
{ 
    if(first == last) return last; 
    In tail(first++); 
    int dupes = 0; 
    while(first != last) { 
     if(*tail++ == *first++) ++dupes; 
     else if(dupes != 0) dupes = 0; 
     else return --tail; 
    } 
    return dupes == 0 ? tail : last; 
} 

El algoritmo anterior tiene una serie ordenada y devuelve el primer elemento único, en el tiempo lineal y el espacio constante. Para obtener todos los únicos en un contenedor, puede usarlo de la siguiente manera:

auto pivot = vec.begin(); 
for(auto i(find_unique(vec.begin(), vec.end())); 
    i != vec.end(); 
    i = find_unique(++i, vec.end())) { 
    std::iter_swap(pivot++, i); 
} 
vec.erase(pivot, vec.end()); 
+0

Para ser sincero, iría con 'std :: sort()' y 'std :: unique()' enfoque. Solo pensé que mostraría una alternativa :) – wilhelmtell

+0

un ejemplo horrible en cualquier caso (rendimiento, etc.), huele como una solución para aquellos que son lo suficientemente flojos como para no verificar el algoritmo biblioteca – newhouse

0

A pesar de que ya está respondida.

orden y único

Cuestiones relacionadas