2011-02-03 22 views
41

Tengo un vector<data> info donde data se define como:clasificar un vector de estructuras

struct data{ 
    string word; 
    int number; 
}; 

Necesito clasificar info por la longitud de la palabra cuerdas. ¿Hay una forma rápida y sencilla de hacerlo?

+1

Si cree que su pregunta fue resuelta, marque una solución como aceptada. –

+0

lo siento.No tuve tiempo de verificar las últimas horas – calccrypto

Respuesta

59

utiliza una función de comparación:

bool compareByLength(const data &a, const data &b) 
{ 
    return a.word.size() < b.word.size(); 
} 

y luego usar std::sort en la cabecera #include <algorithm>:

std::sort(info.begin(), info.end(), compareByLength); 
+0

¿Qué sucede si deseo ordenar el vector de manera lexicográfica de acuerdo con la cadena archivada? (Estoy usando C++ 11 si es importante). ¿Hay alguna forma de abordarlo que no sea definir una función de comparación/usar lambda y usar el operador integral

28

Simplemente haga una función de comparación/funtor:

bool my_cmp(const data& a, const data& b) 
{ 
    // smallest comes first 
    return a.word.size() < b.word.size(); 
} 

std::sort(info.begin(), info.end(), my_cmp); 

o proporcionar una bool operator<(const data& a) const en su clase data:

struct data { 
    string word; 
    int number; 

    bool operator<(const data& a) const 
    { 
     return word.size() < a.word.size(); 
    } 
}; 

o no miembro que Fred dijo:

struct data { 
    string word; 
    int number; 
}; 

bool operator<(const data& a, const data& b) 
{ 
    return a.word.size() < b.word.size(); 
} 

y simplemente llame al std::sort():

std::sort(info.begin(), info.end()); 
+0

Op

+0

¿Por qué 'operator <()' debería ser no miembro? –

+0

@MuriloVasconcelos: Por lo tanto, las conversiones implícitas se aplican al lado izquierdo. –

5

Sí: se puede ordenar usando una función de comparación de encargo:

std::sort(info.begin(), info.end(), my_custom_comparison); 

my_custom_comparison debe ser una función o una clase con una sobrecarga operator() (un funtor) que toma dos objetos data y devuelve un bool que indica si el primero se ha ordenado antes del segundo (es decir, first < second). Alternativamente, puede sobrecargar operator< para su tipo de clase data; operator< es el orden predeterminado utilizado por std::sort.

De cualquier forma, la función de comparación debe producir strict weak ordering de los elementos.

1

Como otros han mencionado, se puede utilizar una función de comparación, pero también se puede sobrecargar el operador < y el funtor predeterminado less<T> funcionará así:

struct data { 
    string word; 
    int number; 
    bool operator < (const data& rhs) const { 
     return word.size() < rhs.word.size(); 
    } 
}; 

Entonces es sólo:

std::sort(info.begin(), info.end()); 

Editar

Como James McNellis señaló, sort en realidad no usa el funcionador less<T> de forma predeterminada. Sin embargo, el resto de la afirmación de que el functor less<T> funcionará también sigue siendo correcto, lo que significa que si quisiera poner struct data en std::map o std::set, esto funcionaría, pero las otras respuestas que proporcionan una función de comparación necesitarían código adicional para trabajar con cualquiera.

+0

Curiosamente, mientras 'std :: map' y' std :: set' se usan de manera predeterminada como 'std :: less ', 'std :: sort' y el resto de las funciones de clasificación se usan de forma predeterminada como' operator <'. Solo notará una diferencia si se especializa en 'std :: less' para hacer algo distinto a lo que hace' operator ''. –

+0

Cuando dije "solo notará una diferencia si ...", estaba equivocado. También notará una diferencia si tiene un contenedor de punteros, p. 'std :: vector v; v.insert (nuevo int); v.insert (nuevo int); std :: sort (v.begin(), v.end()); ', ya que el comportamiento no está definido si se comparan punteros no relacionados con' <'. Dicho esto, por qué querría ordenar un contenedor de punteros por el valor del puntero y no el valor del objeto apuntado, no lo sé. –

Cuestiones relacionadas