Проблема: учитывая два массива строк, для каждой строки в списке (запросе) определите, сколько ее анаграмм находится в другом списке (словаре). Он должен возвращать массив целых чисел. Пример: query = [& ...
3 ответа
Возможно, вы захотите избежать использования (дорогостоящего) Array.prototype.sort()
для обнаружения анаграмм и дать вашему алгоритму обнаружения анаграмм как можно больше сокращений.
Итак, если предположить, что анаграммы должны быть строками одинаковой длины с одинаковым количеством одинаковых символов, вы можете указать что-то вроде этого:
const query = ["a", "nark", "bs", "hack", "stair"],
dictionary = ['hack', 'a', 'rank', 'khac', 'ackh', 'kran', 'rankhacker', 'a', 'ab', 'ba', 'stairs', 'raits'],
charCount = s => [...s].reduce((acc,c) =>
(acc[c]=(acc[c]||0)+1, acc), {}),
areAnagrams = (s1, s2) => {
if(s1.length != s2.length) return false
const s1CharCount = charCount(s1),
s2CharCount = charCount(s2),
result = Object
.keys(s1CharCount)
.every(char =>
s2CharCount[char] == s1CharCount[char])
return result
},
outcome = query.map(word =>
dictionary
.filter(_word => areAnagrams(word, _word))
.length
)
console.log(outcome)
Итак, если я правильно понимаю, строки 'aab'
, 'baa'
, 'aba'
являются анаграммами?
Вместо того, чтобы сортировать их, я бы попытался создать дешевую и быструю подпись.
Если мы преобразуем каждый символ в его код ascii и просуммируем их все, то каждая строка выдаст одно и то же число:
const sum_str = str => str.split('').reduce((n, c) n + c.charCodeAt(0), 0);
sum_str('aab'); //=> 292
sum_str('baa'); //=> 292
sum_str('aba'); //=> 292
Теперь все, что вам нужно сделать, это преобразовать query
и dictionary
в массивы чисел и посчитать, сколько раз каждое число из одного массива встречается в другом:
const qry = ['a', 'nark', 'bs', 'hack', 'stair'];
const dic = ['hack', 'a', 'rank', 'khac', 'ackh', 'kran', 'rankhacker', 'a', 'ab', 'ba', 'stairs', 'raits'];
const sum_str = str => str.split('').reduce((n, c) => n + c.charCodeAt(0), 0);
const count_anagrams = (qry, dic) => {
const qry_sum = qry.map(sum_str);
const dic_sum = dic.map(sum_str);
return qry_sum.map(q => dic_sum.filter(d => d === q).length);
}
count_anagrams(qry, dic);
//=> [2, 2, 0, 3, 1]
Однако у этого метода есть одна большая оговорка. Должна быть возможность получить две строки, например sum_str(a) === sum_str(b)
истинно, но две строки не анаграммы.
Чуть более подробный способ сделать это - но для меня он работает и имеет смысл - для каждого слова в исходном массиве найдите слова в целевом массиве одинаковой длины, а затем подсчитайте те, которые являются анаграммами исходного слова ( анаграмма - это другое слово, состоящее из тех же букв в любом порядке).
Итак, шаги -
Перебрать первый массив и для каждого слова - отфильтровать целевой массив, чтобы получить все слова той же длины, что и это слово (потенциальные анаграммы)
Затем переберите этот массив possibleAnagrams и передайте каждое слово функции, которая проверяет, присутствуют ли все буквы и только буквы в исходном слове (в данном примере - это будет [2, 2, 0, 3, 1]
Сложите все анаграммы слова и передайте счетчик в массив, который регистрируется как окончательный результат.
const queryArr = ["a", "nark", "bs", "hack", "stair"];
const dictionaryArr = ['hack', 'a', 'rank', 'khac', 'ackh', 'kran', 'rankhacker', 'a', 'ab', 'ba', 'stairs', 'raits'];
let anagramsArr = [];
queryArr.forEach(function(query){
let anagramsCount = 0
const potentialAnagrams = dictionaryArr.filter(el => el.length === query.length);
potentialAnagrams.forEach(function(potentialAnagram){
if(isAnagram(query,potentialAnagram)){
anagramsCount++
}
})
anagramsArr.push(anagramsCount);
})
function isAnagram(word1, word2){
let count = 0;
const word1Arr = word1.split('');
const word2Arr = word2.split('');
word1Arr.forEach(function(letter){
if(word2.indexOf(letter) !== -1) {
count++
}
})
return count === word1Arr.length
}
console.log(anagramsArr); //gives [2, 2, 0, 3,1];
Похожие вопросы
Новые вопросы
javascript
По вопросам программирования на ECMAScript (JavaScript / JS) и его различных диалектах / реализациях (кроме ActionScript). Включите все соответствующие теги в свой вопрос; например, [node.js], [jquery], [json] и т. д.