配列プロトタイプで使用可能なsortメソッドを使用すると、配列の要素を並べ替えることができます。 これは、特定のニーズに合わせて並べ替えメカニズムを調整するために使用できるオプションのコールバック関数を受け入れます。

数値の配列については、数値の配列の並べ替えに関する以前の投稿を参照してください。

sortメソッドがどのように機能するかにより、文字列の並べ替えはかなり意見が分かれる可能性があります。

まず、 ECMAScript 標準では、特定の並べ替えアルゴリズムが指定されていません。すべて、各ブラウザーベンダーによって異なります。

第二に、ケーシングは選別時に重要な役割を果たします。 並べ替えが機能するためには、物事を順番に並べる必要があり、これは数字で取得できます。数字は当然順番に並んでいます(1、2、3、4…)。 文字列が比較されるとき、それらは同等の Unicode値に変換されます。これは当然のことながら数値であり、デフォルトでは昇順で順番に並べ替えられます。

文字のUnicode値

各文字のUnicode値(小文字または大文字)を取得するには、charCodeAt文字列メソッドを使用して、指定された文字インデックスの文字コードにアクセスします。

私と一緒にいて。

まず、文字だけでなく文字のユニコード値を取得するのに役立つユーティリティ関数を作成します。 参照しながら参照します。

// get Unicode values of character items in an array
function getCharactersUnicodeValue(characters) {
  const unicodeChart = new Map();
  characters.forEach(character => {
    unicodeChart.set(
      character,
      character.charCodeAt(character.indexOf(character))
    );
  });
  console.table(unicodeChart);
}

// get unicode values of a single character
function getCharacterUnicodeValue(character) {
  const value = character.charCodeAt(character.indexOf(character));
  console.log(value);
}

ここでマップが使用されていることに注意してください。


次のようなユーティリティ関数を呼び出します。

getCharactersUnicodeValue("ABCDEFabcdef".split("")); // array of characters: [ 'A', 'B', 'C', 'D', 'E', 'F', 'a', 'b', 'c', 'd', 'e', 'f' ]
// Result: {character → Unicode Value}
// { A → 65, B → 66, C → 67, D → 68, E → 69, F → 70, a → 97, b → 98, c → 99, d → 100, e → 101, f → 102 }

getCharacterUnicodeValue("A");
// Result: {character → Unicode Value}
// { A → 65 }

そして、ここにさらに別の例があります:

const crocodilian = "crOCoDiliaN".split(""); // array of characters i.e [ 'c', 'r', 'O', 'C', 'o', 'D', 'i', 'l', 'i', 'a', 'N' ]

getCharactersUnicodeValue(crocodilian);

// Result: {character → Unicode Value}
// { c → 99, r → 114, O → 79, C → 67, o → 111, D → 68, i → 105, l → 108, a → 97, N → 78 }

大文字文字が小文字文字の前に表示されることに注意してください。 そして、彼らは順番に来るでしょう。 これは、['Eggs', 'Tail', 'eggs']のようにソートされます。 Taileggsの前に来ることに注意してください。 それは次の理由で予想されます:

getCharactersUnicodeValue(["Eggs", "Tail", "eggs"]);

// Result: {character → Unicode Value}
// { Eggs → 69, Tail → 84, eggs → 101 }
// 84 (T) of Tail comes numerically before 101 (e) of eggs

TL; DR :同じ大文字小文字(すべて上またはすべて下)でのみ文字列が形成される場合の並べ替えは簡単です。 課題は、混合ケースでのみ発生します。

大文字と小文字が混在する文字列の並べ替え

ほとんどの場合、ケーシングに関係なく、大文字と小文字が混在する文字列の配列を並べ替える必要があります。

const things = [ 'nest', 'Eggs', 'bite', 'gator', 'caYman', 'Grip', 'grips', 'Jaw', 'crocodilian', 'Bayou' ];

最終的には次のように並べ替える必要があります。

[ 'Bayou', 'bite', 'caYman', 'crocodilian', 'Eggs', 'gator', 'Grip', 'grips', 'Jaw', 'nest' ]

そしてそうではありません:

[ 'Bayou', 'Eggs', 'Grip', 'Jaw', 'bite', 'caYman', 'crocodilian', 'gator', 'grips', 'nest' ]

試行1:比較関数なし

比較関数なしでsortメソッドを呼び出すと、機能しません。

things.sort();

// ['Bayou', 'Eggs', 'Grip', 'Jaw', 'bite', 'caYman', 'crocodilian', 'gator', 'grips', 'nest']

試行2:比較関数を使用

function sortThings(a, b) {
  if (a > b) {
    return 1;
  } else if (a < b) {
    return -1;
  } else if (a === b) {
    return 0;
  }
}

次に、comparison functionで並べ替えます。

things.sort(sortThings);

// [ 'Bayou', 'Eggs', 'Grip', 'Jaw', 'bite', 'caYman', 'crocodilian', 'gator', 'grips', 'nest' ]

それでも、それは機能しません。 実際、比較関数を作成していない方がよいでしょう。

試行3:比較関数と一般的なケースを使用

問題は、ソートで、things配列要素のデフォルトの混合大文字小文字が引き続き使用されることです。必要なのは、大文字小文字を一般的な大文字小文字に変換することです。小文字または大文字のいずれかで実行できます。

function sortThings(a, b) {
  a = a.toLowerCase();
  b = b.toLowerCase();

  if (a > b) {
    return 1;
  } else if (a < b) {
    return -1;
  } else if (a === b) {
    return 0;
  }
}

または、三項演算子を使用します。

function sortThings(a, b) {
  a = a.toLowerCase();
  b = b.toLowerCase();

  return a > b ? -1 : b > a ? 1 : 0;
}

次に、comparison functionで再度並べ替えます。

things.sort(sortThings);

// ['Bayou', 'bite', 'caYman', 'crocodilian', 'Eggs', 'gator', 'Grip', 'grips', 'Jaw', 'nest' 'eggz']

そして、yippeeそれは今動作します!

しかし、待ってください、もっとあります

ブラウザベンダーには特定の並べ替えアルゴリズムがありますが、私たちが精通している必要のあるいくつかの手法があります。 並べ替えはcharCodeAt(index)ベースで行われます。 2つの比較項目がほぼ類似しているシナリオでは、それらのcharCodeAt(index)が継続的に比較されています。 インデックスが0から始まり、違いが生じるまで。

eggsEggzを例にとってみましょう。

  1. E → 69のUnicode値はe → 101のUnicode値より前にあるため、小文字に変換しない場合、Eggzeggsより前になります。

  2. 同様の大文字小文字(たとえば小文字)への変換がある場合、基本的にeggseggzを比較しています。 e → 101e → 101は同じです。

ランニング:

['Eggz', 'eggs'].sort(sortThings);

// ['eggs', 'Eggz']

最後の文字s → 115 and z → 122が決定論的文字である場合に正しくソートされます。

チェックは次のように行われます。

  • [e→101]ggsと[e→101]ggz/ 101 === 101、次の文字に移動します
  • e[g→103]gsおよびe[g→103]gz/ 103 === 103、次の文字に移動します
  • eg[g→103]sおよびeg[g→103]z/ 103 === 103、次の文字に移動します
  • egg[s→115]とegg[z→122]/明らかに、115は122の前に来ます。

Etvoilà、それが決闘を決定します!

降順

降順で並べ替える必要がある場合は、次のように、比較関数のreturn1をreturn-1と交換するだけです。

function sortThings(a, b) {
  a = a.toLowerCase();
  b = b.toLowerCase();
  if (a > b) {
    return -1;
  } else if (b > a) {
    return 1;
  } else {
    return 0;
  }
}

または:

function sortThings(a, b) {
  a = a.toLowerCase();
  b = b.toLowerCase();
  return a > b ? -1 : b > a ? 1 : 0;
}

または、reverseで、reverse配列メソッドを使用して並べ替えられた配列を指定します。これにより、配列が明らかに逆の順序になります。

things.sort(sortThings).reverse();

代替:localeCompareを使用する

localeCompare 文字列メソッドは、使用される大文字と小文字を区別せずに文字を比較できますが、文字列メソッドであるため、配列で直接使用することはできません。 things配列をlocaleCompare文字列メソッドで並べ替えるには、次のように比較関数としてlocaleCompareを渡します。

things.sort((a, b) => a.localeCompare(b));

// [ 'Bayou', 'bite', 'caYman', 'crocodilian', 'Eggs', 'gator', 'Grip', 'grips', 'Jaw', 'nest' ]

一目でわかるコード

const things = [
  "nest",
  "Eggs",
  "bite",
  "gator",
  "caYman",
  "Grip",
  "grips",
  "Jaw",
  "crocodilian",
  "Bayou"
];
console.log(`unsorted: ${things.join(", ")}`);

function sortThings(a, b) {
  a = a.toLowerCase();
  b = b.toLowerCase();
  return a > b ? 1 : b > a ? -1 : 0;
}

console.log(`sorted:  ${things.sort(sortThings).join(", ")}`);

ソートを続けてください、世界はそれを必要としていることを忘れないでください。