返回课程

过滤字谜

重要性: 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) );

在沙盒中打开包含测试的解决方案。