Отфильтруйте анаграммы
Анаграммы – это слова, у которых те же буквы в том же количестве, но они располагаются в другом порядке.
Например:
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" или "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) {
// разбиваем слово на буквы, сортируем и объединяем снова в строку
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
Два разных слова 'PAN'
и 'nap'
принимают ту же самую форму после сортировки букв – 'anp'
.
Следующая строчка кода помещает слово в объект Map:
map.set(sorted, word);
Если мы когда-либо ещё встретим слово в той же отсортированной форме, тогда это слово перезапишет значение с тем же ключом в объекте. Таким образом, нескольким словам у нас будет всегда соответствовать одна отсортированная форма.
В конце 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) );