Digamos que estou exibindo dados para um usuário em uma grade, relatório, caixa suspensa, etc. Os dados em questão contêm um campo denominado Número da fatura . Este campo contém apenas 2/3 dos números numéricos, mas o outro 1/3 do tempo é uma mistura de alfanuméricos.
Por causa disso, qualquer algoritmo de classificação classificaria alfa numericamente em vez de numericamente . Por esse motivo, 1000 viria muito antes de 99. Porque o primeiro dígito é classificado – não o valor inteiro. Outros itens como 000333 não seriam tratados como “333” e apareceriam antes de 222.
Existe algum padrão aqui? Devo tentar converter todos os valores em um valor numérico e classificá-los de maneira diferente? Como eles se integrariam novamente? Ou a classificação alfanumérica é o caminho correto a seguir?
Comentários
- Se você tiver a capacidade de dizer, use substring para truncar os três primeiros dígitos que possuem o alfabeto e são classificados apenas com base nos três últimos dígitos, no seu caso, dizer ABC333 e 000222 – você pode implementar isso. Claro, durante a exibição, viria na ordem 000222 e ABC333. No entanto, visualmente seria um pouco confuso ver zeros contra poucos numerais e alfabetos contra outros. O que os alfabetos sugerem?
- Comprimentos variáveis, sem SubString. Acho que ver ” 10 ” vir antes de ” 9 ” (na verdade, MUITO antes de 9) seria confuso para os usuários que não ‘ usam alfanuméricos com frequência. Por outro lado, uma mistura pura desses realmente não pode ‘ ser classificada de qualquer maneira que eu possa ver.
- Se estas são faturas, você pode classificá-las por Data ou é explicitamente necessário ordenar de acordo com o próprio número da fatura? Talvez você possa usar outra coluna da tabela e classificá-los de acordo. Supondo que sejam geradas em ordem crescente, uma ordem cronológica de faturas com a mais frequente gerada no topo faria sentido, não? Não tenho certeza sobre para que serve o menu suspenso ou como o usuário pode se beneficiar com a classificação. Se você pudesse nos esclarecer mais sobre o uso do campo, seria muito mais útil!
- Depende ‘ do usuário. Eles podem visualizar esses dados por meio de relatórios, por meio de uma tela de contabilidade que permite verificar os saldos contra a Net 30 (ver todas as faturas de um fornecedor), etc. O usuário escolhe como deseja que a tela ou relatório seja classificado. A data é uma opção. Mas o número da fatura também. Eles não são gerados pelo meu aplicativo. Você encomenda suprimentos, peças, etc. de fornecedores. Esse fornecedor específico devolve o número da fatura para você. Como se você fizesse um pedido em cinco lojas online e recebesse cinco números de pedido. Alguns são numéricos, outros não.
- Você deve converter esses números em um formato numérico. Use isso apenas para classificar os valores alfanuméricos. Os números convertidos não precisam ser mostrados ao usuário para causar mais confusão. No entanto, eu recomendo fortemente que você tenha outra coluna, por exemplo – Data para complementar os Alphanumerals. Visto que classificar Alphanumerals será um pouco confuso, outra coluna para ajudar o usuário a descobrir a data relevante ou outra coisa ajudaria muito.
Resposta
A partir do Windows 7, a Microsoft mudou seu método padrão de classificação de diretórios por nome de arquivo para usar classificação “numérica”. (Algumas informações aqui )
Embora eu não tenha conseguido encontrar uma especificação de seu comportamento, consegui fazer a engenharia reversa. Este algoritmo deve compare duas strings alfanuméricas e determine qual vem primeiro.
-
Divida cada nome de arquivo em partes alfabéticas e numéricas; ou seja, o nome
text123moretext456
torna-se o list {"text"
,"123"
,"moretext"
,"456"
} -
Para cada parte nos dois nomes de divisão, faça a seguinte comparação:
- Se ambas as partes forem estritamente numéricas, compare eles como números
- Se os números forem iguais, compare-os como strings
- Se os strings forem iguais, passe para a próxima parte
- Se ambas as partes forem estritamente letras, compare-as como strings
- Se forem iguais, passe para a próxima parte
- Se ambas as partes forem estritamente numéricas, compare eles como números
- Se você ficar sem peças, o nome com o menor número de peças virá f primeiro
Você termina com uma ordem como a seguinte:
2 12 200000 1000000 a a12 b2 text2 text2a text2a2 text2a12 text2b text12 text12a
Comentários
- Isso é exatamente o que eu estava procurando e a ordem de classificação resultante faz sentido. Obrigado!
Resposta
Esta pergunta (e especialmente a resposta de @Harrison Paine “) me ajudou em meu projeto e desejo fornecer a implementação [javascript] de sua resposta para referência futura.Aqui está a classificação function
:
var win7sort = function(a, b) { var regex = /[^\d]+|\d+/g; // Split each filename into alphabetical and numeric parts var ar = a.match(regex); var br = b.match(regex); var localeCompare; // For each part in the two split names, perform the following comparison: for(var ia in ar) { for(var ib in br) { var ari = ar[ib]; if(ari == undefined) { ari = ""; } var bri = br[ib]; if(bri == undefined) { bri = ""; } // If both parts are strictly numeric, compare them as numbers if(!isNaN(ari) && !isNaN(bri)) { localeCompare = ari.localeCompare(bri, {}, { numeric: true }); } else { localeCompare = ari.localeCompare(bri, {}, { ignorePunctuation: true, sensitivity: "base" }); } if(localeCompare != 0) { // If you run out of parts, the name with the fewest parts comes first return localeCompare; } // If they"re the same, move on to the next part } } return localeCompare; };
E aqui está como usá-lo:
var list = ["1", "a", "z", "new folder 2", "new folder 03", "new folder 03-a", "new folder 039", "new folder 5", "new folder 41", "2", "21", "3", "41", "100"]; var sortedList = list.sort(win7sort);