2015-03-10 19 views
5

testati in ultima Firefox e Chrome (che hanno un locale 'de' sul mio sistema):localeCompare mostra un comportamento incoerente quando sono ordinati parole con i principali caratteri di dieresi

"Ä".localeCompare("A") 

mi dà 1, il che significa che crede "Ä" dovrebbe apparire dopo"A" in un ordine ordinato, che è corretto.

Ma:

"Ägypten".localeCompare("Algerien") 

mi dà -1, il che significa che crede "Ägypten" dovrebbe apparire prima"Algerien" in un modo ordinato.

Perché? Perché guarda oltre il primo carattere di ogni stringa, se dice che il primo carattere della prima stringa dovrebbe apparire dopo il primo carattere della seconda stringa quando lo si controlla da solo?

risposta

1

Ecco metodo giusto per le vostre esigenze, copia incolla questo metodo:

parse ricorsiva di stringhe e dare locale char comparazione risultare non stringa :)

RISULTATO FINALE bug fisso, ha aggiunto confrontare (arresto errata o ciclo ricorsivo) a intere stringhe:

String.prototype.MylocaleCompare = function (right, idx){ 
    idx = (idx == undefined) ? 0 : idx++; 

    var run = right.length <= this.length ? (idx < right.length - 1 ? true : false) : (idx < this.length - 1 ? true : false); 


    if (!run) 
    { 
     if (this[0].localeCompare(right[0]) == 0) 
      { 
       return this.localeCompare(right); 
      } 
      else 
      { 
       return this[0].localeCompare(right[0]) 
      } 
    } 

    if(this.localeCompare(right) != this[0].localeCompare(right[0])) 
    { 
     var myLeft = this.slice(1, this.length); 
     var myRight = right.slice(1, right.length); 
     if (myLeft.localeCompare(myRight) != myLeft[0].localeCompare(myRight[0])) 
     { 
      return myLeft.MylocaleCompare(myRight, idx); 
     } 
     else 
     { 
      if (this[0].localeCompare(right[0]) == 0) 
      { 
       return myLeft.MylocaleCompare(myRight, idx); 
      } 
      else 
      { 
       return this[0].localeCompare(right[0]) 
      } 
     } 
    } 
    else 
    { 
     return this.localeCompare(right); 
    } 

} 
+0

Il tuo algoritmo sembra funzionare, lo hai programmato da solo o lo hai da qualche parte? – wnstnsmth

+0

@wnstnsmth l'ho programmato io stesso, ma non è completamente funzionante (il mio male qui), spero di trovare il tempo per sistemarlo oggi, o domani tornerò con la correzione :) – SilentTremor

+0

Sì, ho trovato un bug : Se la stringa a è un sottoinsieme di stringa b, in questo modo (a === "Indien", b === "Indien (CA)"), Firefox genera un errore che myLeft [0] non è definito. – wnstnsmth

1

http://en.wikipedia.org/wiki/Diaeresis_(diacritic)#Printing_conventions_in_German

“Quando alfabetico ordinamento tedesco parole, l'umlaut è di solito non distingue dal vocale sottostante, anche se due parole differiscono solo per una dieresi, quello umlaut arriva secondo [...]
“ V'è un secondo sistema in uso limitato, per lo più per l'ordinamento nomi (colloquialmente chiamato "elenco telefonico di smistamento"), che tratta ü come ue, e così via.”

Supponendo che il s Viene applicato un tipo di algoritmo di ordinamento, quindi i risultati che si stanno vedendo hanno senso.

Ä sarebbe diventato Ae, e che è “più a lungo”, allora la vostra altro valore A, quindi l'ordinamento A prima Ae e per questo A prima Ä sarebbe corretto (e come hai detto tu stesso, si considera che questo sia corretto, e anche dal primo algoritmo che tratta lo Ä come A sarebbe anche corretto).

Ora Ägypten diventa Aegypten a fini di cernita, e per esso deve apparire prima Algerien nella stessa logica di smistamento - le prime lettere di entrambi i termini sono uguali, per cui spetta ai secondi per determinare l'ordinamento e e ha un valore di ordinamento lessicograficamente inferiore a l. Pertanto, Aegypten prima dello Algerien, ovvero Ägypten prima dello Algerien.


Wikipedia tedesca elabora ancora di più su questo (http://de.wikipedia.org/wiki/Alphabetische_Sortierung#Einsortierungsregeln_f.C3.BCr_weitere_Buchstaben), e fa notare che ci sono due varianti della norma DIN 5007. relativo

DIN 5007 Variante 1 dice, ä deve essere trattata come a, ö come o e ü come u, e che questo tipo di ordinamento doveva essere usato per dizionari e simili.

variante DIN 5007 1 dice l'altra cosa, ä da trattare come ae, ecc., e questo deve essere usato principalmente per elenchi di nomi come gli elenchi telefonici.

Wikipedia continua a dire che questo tenga conto che ci potrebbe essere più di una forma di ortografia per i nomi personali (cognome di qualcuno potrebbe essere Moeller o Möller, esistono entrambe le versioni), mentre per parole un dizionario di solito c'è solo uno ortografia che è considerata corretta.

Ora, suppongo che la domanda sul prezzo rimanente sia: Posso ottenere i browser per applicare l'altra forma di ordinamento per le impostazioni internazionali tedesche? Per essere sincero, non lo so.

Potrebbe sicuramente essere desiderabile essere in grado di scegliere tra queste due forme di ordinamento, perché come la Wikipedia dice i nomi di persone Moeller e Möller esistere, ma c'è solo Ägypten e non Aegypten quando arriva a un dizionario.

+0

senso, ma, c'è questa cosa. Quando faccio '[" Ä "," A "]. Sort();' e '['Ägypten', 'Algerien']. Sort();' ottengo risultati uguali - umlaut viene secondo, quindi sembra che lì è una sorta di errore all'interno di 'compareLocale' dopo tutto. ' – Eternal1

+1

@ Eternal1:' Array.sort' non è consapevole delle impostazioni internazionali, pertanto verranno applicate le regole di confronto delle stringhe "normali". E poiché le stringhe non hanno un semplice metodo 'compare', suppongo che ciò avvenga sulla base di valori di byte, non di caratteri. – CBroe

+0

Grazie per questa risposta elaborata. Mi chiedo se l'implementazione di localeCompare sia documentata da qualche parte. Ho pensato che avrebbe fatto il confronto unicode carattere per carattere, e non convertire "ä" in "ae" prima come nella variante DIN5007 2. Che non ha molto senso nei miei occhi. – wnstnsmth

Problemi correlati