web-dev-qa-db-ja.com

JavaScriptでUnicode文字列を比較する方法は?

JavaScriptで書いたとき"Ł" > "Z"trueを返します。 Unicode順では、もちろんfalseになります。これを修正するには?私のサイトはUTF-8を使用しています。

41
Tomasz Wysocki

ECMAScript Internationalization API で導入された Intl.Collator または String.prototype.localeCompare を使用できます。

"Ł".localeCompare("Z", "pl");              // -1
new Intl.Collator("pl").compare("Ł","Z");  // -1

-1は、必要に応じて、ŁZより前に来ることを意味します。

ただし、最新のブラウザでのみ機能します。

34
Oriol

カスタムソートに役立つフランス語のアルファベットの例を次に示します。

_var alpha = function(alphabet, dir, caseSensitive){
  return function(a, b){
    var pos = 0,
      min = Math.min(a.length, b.length);
    dir = dir || 1;
    caseSensitive = caseSensitive || false;
    if(!caseSensitive){
      a = a.toLowerCase();
      b = b.toLowerCase();
    }
    while(a.charAt(pos) === b.charAt(pos) && pos < min){ pos++; }
    return alphabet.indexOf(a.charAt(pos)) > alphabet.indexOf(b.charAt(pos)) ?
      dir:-dir;
  };
};
_

文字列の配列aで使用するには:

_a.sort(
  alpha('ABCDEFGHIJKLMNOPQRSTUVWXYZaàâäbcçdeéèêëfghiïîjklmnñoôöpqrstuûüvwxyÿz')
);
_

alpha()の2番目のパラメーターとして_1_または_-1_を追加して、昇順または降順で並べ替えます。
大文字と小文字を区別して並べ替えるには、3番目のパラメータとしてtrueを追加します。

アルファベットのリストに数字や特殊文字を追加する必要があるかもしれません

19
Mic

localeCompare()を使用して独自のソート関数を作成できる場合があります。少なくとも トピックに関するMDCの記事 によると、正しくソートする必要があります。

それがうまくいかない場合は、以下に 興味深いSO質問 を示します。ここで、OPは文字列置換を使用して「ブルートフォース」のソートメカニズムを構築します。

また、その質問では、OPはロケール対応のソートを行うjQueryテーブルソータープラグイン用に カスタムtextExtract関数 を構築する方法を示しています-おそらく一見の価値もあります。

編集:完全に遠い考えとして-これがまったく可能かどうか、特にパフォーマンスの懸念のために、私が考えているのは、とにかく、バックエンドのPHP/mySQLでは、AjaxクエリをmySQLインスタンスに送信して、そこでソートする可能性について言及したいと思います。 mySQLは、ロケール対応データのソートに優れています。 ORDER BY xyz COLLATE utf8_polish_ciCOLLATE utf8_german_ci....これらの照合は、すべての並べ替えの問題を一度に処理します。

13
Pekka

言及されていない文字のマイクのコードが改善されました:

var alpha = function(alphabet, dir, caseSensitive){
  dir = dir || 1;
  function compareLetters(a, b) {
    var ia = alphabet.indexOf(a);
    var ib = alphabet.indexOf(b);
    if(ia === -1 || ib === -1) {
      if(ib !== -1)
        return a > 'a';
      if(ia !== -1)
        return 'a' > b;
      return a > b;
    }
    return ia > ib;
  }
  return function(a, b){
    var pos = 0;
    var min = Math.min(a.length, b.length);
    caseSensitive = caseSensitive || false;
    if(!caseSensitive){
      a = a.toLowerCase();
      b = b.toLowerCase();
    }
    while(a.charAt(pos) === b.charAt(pos) && pos < min){ pos++; }
    return compareLetters(a.charAt(pos), b.charAt(pos)) ? dir:-dir;
  };
};

function assert(bCondition, sErrorMessage) {
      if (!bCondition) {
          throw new Error(sErrorMessage);
      }
}

assert(alpha("bac")("a", "b") === 1, "b is first than a");
assert(alpha("abc")("ac", "a") === 1, "shorter string is first than longer string");
assert(alpha("abc")("1abc", "0abc") === 1, "non-mentioned chars are compared as normal");
assert(alpha("abc")("0abc", "1abc") === -1, "non-mentioned chars are compared as normal [2]");
assert(alpha("abc")("0abc", "bbc") === -1, "non-mentioned chars are compared with mentioned chars in special way");
assert(alpha("abc")("zabc", "abc") === 1, "non-mentioned chars are compared with mentioned chars in special way [2]");
9
Tomasz Wysocki

2つのsortkey文字列を保持する必要があります。 1つは1次の場合で、ドイツ語のä= a(1次a-> a)とフランス語のé= e(1次のソートキーe-> e)であり、もう1つはäがaの後に来る(2次でa-> azzzzを変換する) key)またはéがeの後に続きます(2次キーe-> ezzzz)。特にチェコ語では、一部の文字は文字の変形(áéí…)ですが、他の文字はリストで完全な形で立っています(ABCČD…GHChI…RŘSŠT…)。さらに、ダイグラフを単一の文字と見なす問題(主ch-> hzzzz)。ささいな問題はありません。JS内に解決策があるはずです。

0
xandru