· 7 years ago · Jan 25, 2019, 08:56 PM
1# Prompt
2
3You are given an array of strings only (could be words, phrases etc). Create a function to find all the anagrams within that array. The output should be an array where each element in the array is itself an array of anagrams.
4
5---
6
7# Examples
8
9```js
10const words = ['cat', 'act', 'ignore', 'a phrase', 'tape', 'pate', 'e hpsara'];
11listAnagrams(words);
12// [['cat', 'act'], ['a phrase', 'e hpsara'], ['tape', 'pate']]
13```
14
15Notice that `'ignore'` does not appear in the output.
16
17---
18
19# Solutions
20
21One effective approach is:
22
231. Sort each string in the array
242. Create a hash table of these sorted strings and arrays of words that match
253. Go through all of the values in that hash table and add them to the output array if they contain at least two elements
26
27---
28
29```js
30function listAnagrams (wordsArr) {
31 const wordsTable = {};
32 wordsArr.forEach(function (word) {
33 // in order to sort a string we must convert it into an array of
34 // its characters
35 const wordKey = word.split('').sort().join('');
36 // if this sorted entry already exists push the word into the array
37 // with its sibling anagrams
38 if (wordsTable[wordKey]) {
39 wordsTable[wordKey].push(word);
40 }
41 // or if we have not yet visited any anagrams of this word, create
42 // a new array for it
43 else wordsTable[wordKey] = [word];
44 });
45 const output = [];
46 Object.keys(wordsTable).forEach(function (wordKey) {
47 const anagrams = wordsTable[wordKey];
48 // only include lists with more than one anagram
49 if (anagrams.length > 1) {
50 output.push(anagrams);
51 }
52 });
53 return output;
54}
55```
56
57---
58
59"Minified" solution:
60
61```js
62const anagramDetector = strArr => Object.values(
63 strArr.reduce((hash, word) => {
64 const wordSort = word.split('').sort().join('');
65 if (hash[wordSort]) hash[wordSort].push(word)
66 else hash[wordSort] = [word];
67 return hash;
68 }, {})).filter(anagrams => anagrams.length > 1)
69```