Here is the HashMap based implementation of the function checking whether two strings are anagrams:
Example:
isAnagram("SAVE", "VASE") // returns true
isAnagram("SAV", "VASE") // returns false
isAnagram("SAVE", "VAS") // returns false
isAnagram("SAVE", "VAEE") // returns false
My implementation:
def isAnagram(value1: String, value2: String): Boolean = {
value1.length == value2.length && {
val index = new mutable.HashMap[Char, Int]()
def addToIndex(c: Char) = index(c) = index.getOrElse(c, 0) + 1
value1.foreach(c => addToIndex(c))
def decrementAndCheckInIndex(c: Char): Boolean = index.get(c) match {
case None => false
case Some(count) => index(c) = count - 1; true
}
value2.forall(decrementAndCheckInIndex) && index.forall { case (key, value) => value == 0 }
}
}
Could you please provide feedback on this code. I am interested in the mutable data structure use here, is it ok? And in general, what can I make better?
1 Answer 1
It seems to me that groupBy()
will do something very similar to your addToIndex()
. The result is an immutable.Map[Char,String]
instead of a mutable.HashMap[Char, Int]
, so the question is: which is better/easier for comparison purposes.
It turns out that the simple ==
evaluation is sufficiently deep to handle this.
def isAnagram(value1: String, value2: String): Boolean =
value1.groupBy(identity) == value2.groupBy(identity)
Another, rather obvious, anagram test is simply:
value1.sorted == value2.sorted
I think, for long strings, grouping/indexing might be more efficient than sorting since each string is traversed only once. On the other hand, comparison for equality might be more complex for Map
s than it would be for String
s.
Explore related questions
See similar questions with these tags.