アナグラムをフィルタする
重要性: 4
アナグラム は同じ文字を同じ数だけ持っていますが、異なる順序である単語です。
例えば:
nap - pan
ear - are - era
cheaters - hectares - teachers
アナグラムで整理された配列を返す関数 aclean(arr)
を書いてください。
例:
let arr = ["nap", "teachers", "cheaters", "PAN", "ear", "era", "hectares"];
alert( aclean(arr) ); // "nap,teachers,ear" or "PAN,cheaters,era"
すべてのアナグラム・グループから、どれかは問いませんが1つの単語だけ残してください。
すべてのアナグラムを見つけるために、すべての単語を文字に分割してソートしましょう。文字でソートしたとき、すべてのアナグラムは同じです。
例:
nap, pan -> anp
ear, era, are -> aer
cheaters, hectares, teachers -> aceehrst
...
文字でソートされたバリアントをマップキーとして使用して、各キーごとに1つの値しか格納しません。:
function aclean(arr) {
let map = new Map();
for (let word of arr) {
// 単語を文字で分割し、ソートして結合し直します
let sorted = word.toLowerCase().split('').sort().join(''); // (*)
map.set(sorted, word);
}
return Array.from(map.values());
}
let arr = ["nap", "teachers", "cheaters", "PAN", "ear", "era", "hectares"];
alert( aclean(arr) );
文字ソートは行 (*)
での呼び出しチェーンで行われています。
便利のために、複数行に分割しましょう:
let sorted = arr[i] // PAN
.toLowerCase() // pan
.split('') // ['p','a','n']
.sort() // ['a','n','p']
.join(''); // anp
2つの異なる単語 'PAN'
と 'nap'
は同じ文字デソートされた形式 'anp'
になります。
次の行は単語をマップにセットしています。:
map.set(sorted, word);
同じ文字でソートされた単語がもう一度あった場合には、マップ内の同じキーで前の値を上書きします。なので、私たちはいつも文字形式毎に最大1つの単語を持ちます。
最後に、Array.from(map.values())
でマップの値の反復をし(結果の中でキーは必要ありません)、それらの配列を返却します。
ここでは、Map
の代わりに通常のオブジェクトを使うこともできます。なぜならキーが文字列だからです。
その場合の解答は次のようになります:
function aclean(arr) {
let obj = {};
for (let i = 0; i < arr.length; i++) {
let sorted = arr[i].toLowerCase().split("").sort().join("");
obj[sorted] = arr[i];
}
return Array.from(Object.values(obj));
}
let arr = ["nap", "teachers", "cheaters", "PAN", "ear", "era", "hectares"];
alert( aclean(arr) );
function aclean(arr) {
let map = new Map();
for(let word of arr) {
let sorted = word.toLowerCase().split("").sort().join("");
map.set(sorted, word);
}
return Array.from(map.values());
}