Photo by Piotr Łaskawski on Unsplash
Creating an Anagram Checker Function in JavaScript
Learn what an Anagram is and how to build a simple Anagram Checker Function in JavaScript
A few days ago, I saw this tweet from John about his experience during a recent interview. I bet that we developers have had similar experiences, either while solving LeetCode problems or during an actual interview.
I know—we have all been there. It's more frustrating if the word “Anagram” is new to you, especially if it's not a word we hear or use in our everyday conversation or you are not a native English speaker.
But don't worry. This article will explain an Anagram and create a simple Anagram checker function with JavaScript.
You'll need some JavaScript know-how to get the most out of this article.
Let’s dive in…
What is an Anagram?
An anagram is a word or phrase formed by rearranging the letters of another word or phrase, typically using all the original letters exactly once. The letters are shuffled around to create a new, meaningful word or phrase.
Let’s say you have a word or phrase labeled X. You take the letters that make X and shuffle or rearrange their positions to make a new word or phrase, which we will label Y. We can now refer to Y as an anagram of X.
Here is a good example of an Anagram, Notice how the letters of the word Silent are being rearranged to form a new word Listen, using each letter only once.
Examples of an Anagram
Here are some examples of words or phrases that qualify as anagrams
Silent —> Listen
Conversations —> Voices rant on
The eyes —> They see
Debit card —> Bad credit
New York Times —> Monkeys write
Coronavirus —> carnivorous
Cheater —> teacher
Forty five —> over fifty
Santa —> satan
Dormitory —> Dirty room
Etc…
The Solution
Most anagram questions will ask you to compare two words to know if one is an anagram of the other. So to solve this problem, you will assume that :
Extra characters like “@”, “$”, “!”, etc and whitespaces will be ignored
You will be working with lowercase letters only.
Now, let’s get into the solutions to the problem.
Using regex,split(), sort() and join() methods
function anagramCheckerOne(str1, str2) {
// Helper function to clean and sort a string
const cleanSortString = (str) =>
str
.replace(/[^a-z]/gi, "")
.toLowerCase()
.split("")
.sort()
.join("");
// Compare the cleaned, sorted versions of both strings
return cleanSortString(str1) === cleanSortString(str2);
}
// Example usage:
console.log(anagramCheckerOne("Listen", "Silent")); //true
console.log(anagramCheckerOne("Conversations", "Conversations")); //true
console.log(anagramCheckerOne("Hello", "World")); //false
Explanation:
The
anagramChecker
function accepts two parametersstr1
andstr2
and returnstrue
if the results of the cleaned-up parameters match andfalse
if they don’t.replace(/[^a-z]/gi, "")
removes any characters that aren't alphabetic (like spaces, and punctuation).toLowerCase()
ensures the comparison is case-insensitivesplit('').sort().join('')
splits the string into an array of characters, sorts them, and joins them back into a string. If both strings are anagrams, their sorted versions will be identical.
Using Character Frequency Map
function anagramCheckerTwo(str1,str2){
// Helper function to create a character frequency map
const createCharMap = (str) => {
// Create a frequency map for each string
const charMap = {};
for (const char of str.toLowerCase()) {
// Only consider alphabetic characters
if (char >= "a" && char <= "z") {
charMap[char] = (charMap[char] || 0) + 1;
}
}
return charMap;
};
// frequency map for both strings
const charMap1 = createCharMap(str1);
const charMap2 = createCharMap(str2);
// If lengths are different, they cannot be anagrams
if(Object.keys(charMap1).length !== Object.keys(charMap2).length){
return false
}
// Compare the two character maps
for(const char in charMap1){
if(charMap1[char] !== charMap2[char]){
// If the character is not found or count is zero, not an anagram
return false
}
}
return true // If we reach here, they are anagrams
}
// Example usage:
console.log(anagramCheckerTwo("Listen", "Silent"));//true
console.log(anagramCheckerTwo("Conversations", "Conversations"));//true
console.log(anagramCheckerTwo("Hello", "World"));//false
Explanation:
The character map here contains the string's unique characters in a map or object. It uses the letter as a key and the string's frequency of occurrence as the value.
The
createCharMap
function builds an object that keeps track of each letter's count. This avoids the need for sorting and regex.There is a check to ensure that only characters from letters 'a' to 'z' are included in the anagram checker function, ignoring spaces and non-alphabetic characters.
The two maps created are compared by checking that they have the same number of unique characters and that each character occurs at the same frequency in both maps.
Using the …spread operator
const anagramCheckerThree = (str1, str2) =>
[...str1.toLowerCase().replace(/\W/g, "")].sort().join("") ===
[...str2.toLowerCase().replace(/\W/g, "")].sort().join("");
// Example usage:
console.log(anagramCheckerThree("Listen", "Silent"));//true
console.log(anagramCheckerThree("Conversations", "Conversations"));//true
console.log(anagramCheckerThree("Hello", "World"));//false
Explanation:
[...]
: Uses the spread operator to split each string into an array of characters.toLowerCase()
: Converts both strings to lowercase for case-insensitive comparison.sort()
: Sort the arrays alphabetically.join('')
: Joins the sorted arrays back into strings.===
: Compares the two sorted strings directly.\W
(in thereplace()
method) removes any non-word characters, including spaces.
Using the split() method
const anagramCheckerFour = (str1, str2) =>
((s) => s.split("").sort().join(""))(
str1.replace(/\s+/g, "").toLowerCase()
) ===
((s) => s.split("").sort().join(""))(str2.replace(/\s+/g, "").toLowerCase());
// Example usage:
console.log(anagramCheckerFour("Listen", "Silent"));//true
console.log(anagramCheckerFour("Conversations", "Conversations"));//true
console.log(anagramCheckerFour("Hello", "World"));//false
Explanation:
The function uses an arrow function to normalize the input strings by removing spaces and converting them to lowercase.
(s => s.split('').sort().join(''))
: This is an immediately invoked arrow function expression (IIAFE). It takes the cleaned string, splits it into an array of characters, sorts them alphabetically, and then joins them back into a sorted string.replace(/\s+/g, '')
: This part removes all whitespace (spaces, tabs, etc.) fromstr1
using a regular expression (\s+
matches any whitespace andg
is for the global flag to replace all occurrences).toLowerCase()
: Converts the entire string to lowercase to ensure the comparison is case-insensitive.The cleaned and sorted versions of
str1
andstr2
are then directly compared using===
.If they are identical, it means the two original strings are anagrams, and the function returns
true
. Otherwise, it returnsfalse
.
Performance Metrics
The Sorting-Based Approaches (anagramCheckerOne
, anagramCheckerThree
, anagramCheckerFour
) are heavily dependent on sorting, which is O(n log n)
but generally performs well with small to medium strings, but sorting can become costly with larger input sizes.
The Frequency Map Approach (anagramCheckerTwo
) has a linear complexity, O(n)
making it faster for larger inputs but its memory consumption may be higher due to the use of object maps.
So before choosing a function, consider the size of the input data—use a more efficient algorithm for larger inputs (like anagramCheckerTwo
with O(n)
complexity) and prioritize simplicity and readability for smaller inputs where performance impact is minimal.
Pros and Cons
Here is a table with the pros and cons of each function to give you better insight and help you decide on what to use when next you have to deal with anagram-related questions.
Function | Pros | Cons |
anagramCheckerone | Simple to understand, straightforward implementation | Regex can be slower; sorting is O(n log n) |
anagramCheckerTwo | Fastest for large strings (O(n) ), avoids sorting | Slightly more code consumes extra space with frequency maps |
anagramCheckerThree | Clean one-liner, a good balance between simplicity & brevity | Uses sorting, which can be slower for large inputs |
anagramCheckerFour | Another clean one-liner uses a spread operator neatly | Also sorting-based, regex is used for cleaning |
Conclusion
The anagram checker function is a common technical interview problem, that tests your knowledge about string manipulation, data structures, and algorithm efficiency. This article covered the concept of anagrams and evaluated various checker functions, analyzing their performance, pros, and cons.
Character-sorting methods offer simple, readable solutions for smaller datasets where performance isn’t critical. In contrast, frequency map approaches, with linear complexity, are more efficient for larger datasets, making them ideal when speed is essential.
In summary, the choice between simplicity and efficiency depends on the dataset size. Understanding each method’s strengths and weaknesses helps in both interviews and real-world scenarios, enabling smarter, more informed solutions.
Got any questions or additions? Please leave a comment.
Thank you for reading.