Me gustaría ordenar las cadenas alfanuméricas de la forma en que un ser humano las clasificaría. Es decir, "A2" viene antes que "A10", y "a" ciertamente viene antes de "Z"! ¿Hay alguna forma de hacerlo sin escribir un mini-analizador? Idealmente, también pondría "A1B1" antes de "A1B10". Veo la pregunta "Natural (human alpha-numeric) sort in Microsoft SQL 2005" con una posible respuesta, pero usa varias funciones de la biblioteca, al igual que "Sorting Strings for Humans with IComparer".Cadena de clasificación C++ como un ser humano?
A continuación se muestra un caso de prueba que en la actualidad no:
#include <set>
#include <iterator>
#include <iostream>
#include <vector>
#include <cassert>
template <typename T>
struct LexicographicSort {
inline bool operator() (const T& lhs, const T& rhs) const{
std::ostringstream s1,s2;
s1 << toLower(lhs); s2 << toLower(rhs);
bool less = s1.str() < s2.str();
//Answer: bool less = doj::alphanum_less<std::string>()(s1.str(), s2.str());
std::cout<<s1.str()<<" "<<s2.str()<<" "<<less<<"\n";
return less;
}
inline std::string toLower(const std::string& str) const {
std::string newString("");
for (std::string::const_iterator charIt = str.begin();
charIt!=str.end();++charIt) {
newString.push_back(std::tolower(*charIt));
}
return newString;
}
};
int main(void) {
const std::string reference[5] = {"ab","B","c1","c2","c10"};
std::vector<std::string> referenceStrings(&(reference[0]), &(reference[5]));
//Insert in reverse order so we know they get sorted
std::set<std::string,LexicographicSort<std::string> > strings(referenceStrings.rbegin(), referenceStrings.rend());
std::cout<<"Items:\n";
std::copy(strings.begin(), strings.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
std::vector<std::string> sortedStrings(strings.begin(), strings.end());
assert(sortedStrings == referenceStrings);
}
¿Hay alguna razón por la que esté utilizando un 'conjunto' y no simplemente' ordenar'-un 'vector'? –
Primero, ¿cómo clasificaría A1B2 en relación con A2B1? Nunca he hecho esto, pero probablemente comenzaría por romper la cuerda en pedazos. Texto, números, texto, números, etcétera. Luego, clasifique de la misma manera que lo haría con cualquier otra estructura de datos con múltiples miembros, en el entendido de que los bits numéricos se clasifican como números y no como cadenas. –
@Dibling: Sin motivo particular. @Zickefoose: Ordenaría (ascendente) como: A1B2, A1B10, A2B1. Creo que puede que tengas razón de que tendré que hacer un poco de lexing primitivo, pero preferiría evitar algo propenso a errores si puedo evitarlo. –