过滤字谜
重要性: 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"
每个字谜组中应该只保留一个词,无论哪个词。
要找到所有字谜,让我们将每个词拆分成字母并排序。当字母排序后,所有字谜都是相同的。
例如
nap, pan -> anp
ear, era, are -> aer
cheaters, hectares, teachers -> aceehrst
...
我们将使用字母排序后的变体作为 map 的键,以存储每个键只有一个值。
function aclean(arr) {
let map = new Map();
for (let word of arr) {
// split the word by letters, sort them and join back
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 = word // PAN
.toLowerCase() // pan
.split('') // ['p','a','n']
.sort() // ['a','n','p']
.join(''); // anp
两个不同的词 'PAN'
和 'nap'
接收相同的字母排序形式 'anp'
。
下一行将该词放入 map 中
map.set(sorted, word);
如果我们再次遇到一个具有相同字母排序形式的词,那么它将用具有相同键的 map 中的先前值覆盖它。因此,我们最多将每个字母形式保留一个词。
最后,Array.from(map.values())
获取 map 值的可迭代对象(我们不需要结果中的键)并返回它们的数组。
在这里,我们也可以使用普通对象而不是 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 Object.values(obj);
}
let arr = ["nap", "teachers", "cheaters", "PAN", "ear", "era", "hectares"];
alert( aclean(arr) );