Find all the anagrams of a word from a list

trying to solve a task from codewars:

Write a function that will find all the anagrams of a word from a list. You will be given two inputs a word and an array with words. You should return an array of all the anagrams or an empty array if there are none.

anagrams('abba', ['aabb', 'abcd', 'bbaa', 'dada']) => ['aabb', 'bbaa']

Here's my solution:

function anagrams(str, arr) {
  let newArr = [];
  for(let i = 0; i < arr.length; i++) {
    let result = str.split('').every(function(letter) {
      return arr[i].indexOf(letter) != -1;
    });
    if(result === true) {
      newArr.push(arr[i]);
    }
  }
  return newArr;
}

Which is not working correctly: it displays ["aabb","abcd","bbaa"] when ['aabb', 'bbaa'] is required.

Thank you in advance.

2 answers

  • answered 2021-06-10 11:13 dottomato

    I think you also need to manage the counts of letters. You get abcd in your output because abba is present in it according to this piece of code.

    let result = str.split('').every(function(letter) {
          return arr[i].indexOf(letter) != -1;
    });
    

  • answered 2021-06-10 11:25 trincot

    Although your function correctly checks that each letter of the word occurs in the potential anagram of it, it does not check that the number of duplicates of that letter is the same.

    You could solve this by first determining the count of each distinct letter:

    function getCounts(str) {
        letterCount = {};
        for (let letter of str) {
            letterCount[letter] ??= 0;
            letterCount[letter]++;
        }
        return letterCount;
    }
    
    function anagrams(str, arr) {
        counts = getCounts(str);
        return arr.filter(anagram =>
            anagram.length === str.length &&
            Object.entries(getCounts(anagram)).every(([letter, count]) =>
                counts[letter] === count
            )
        );
    }
    
    console.log(anagrams('abba', ['aabb', 'abcd', 'bbaa', 'dada']));