patternModerate
Simple anagram finder using Scala and some Scalaz
Viewed 0 times
simplefinderscalaanagramusingsomeandscalaz
Problem
I'd like to hear some thoughts on my simple anagram finder, written in Scala. I mainly wrote this as a first go at writing some serious Scala, and I wanted to try out the Scalaz library.
I'm coming from a Java background, with minimal experience with functional languages. Things I'd ideally like feedback on:
I know that I've not covered all test cases, but this was enough to get me up and running.
General algorithm:
Signature class
Notes:
I'm sure I'd be able to take the word as a parameter and manipulate it to be in alphabetical order, rather than having a
Anagram Finder class
Notes:
I really wanted to just have
I'm coming from a Java background, with minimal experience with functional languages. Things I'd ideally like feedback on:
- Any improvements to make it less imperative
- Any other uses of library code, like Scalaz
I know that I've not covered all test cases, but this was enough to get me up and running.
General algorithm:
- Parse a list of words. Turn each word into lower case, sort alphabetically and treat that as the 'signature' of the word.
- Insert signature and word into a map, with the key being the signature, and the value being a set (or list) of words with the same signature
- Retrieval is simply looking up a word based on its signature
Signature class
case class Stem(word: String) {
val stem: List[Char] = word.toLowerCase.trim.toList.sortWith((e1, e2) => (e1 s.stem == stem
case _ => false
}
override def hashCode = stem.hashCode
override def toString = stem.mkString("Stem(", "", ")")
}Notes:
I'm sure I'd be able to take the word as a parameter and manipulate it to be in alphabetical order, rather than having a
stem field. I'm sure I'd have been able to omit the equals and hashCode methods then, but I couldn't work out how to do that. I think maybe because I'm using a case class here?Anagram Finder class
import scalaz._
import Scalaz._
class AnagramFinder(words: List[String]) {
implicit def string2Stem(s: String): Stem = Stem(s)
val mapping = createMapping(words)
def createMapping(words: List[String]) = {
var anagrams: Map[Stem, Set[String]] = Map()
words.foreach(s => anagrams = anagrams |+| Map(Stem(s) -> Set(s)))
anagrams
}
def find(word: String): Option[Set[String]] = mapping.get(word)
}Notes:
I really wanted to just have
anagrams |+| Map(Stem(s) -> Set(s)) in my foreach, butSolution
Some suggestions to improve your code:
xs.sortWith((e1, e2) => (e1 Stem doesn't work in string -> set because -> already needs an implicit conversion and you are not allowed to apply multiple ones at once. When you use tuple notation (string, set), your implicit conversion is applied.Code Snippets
object Stem {
def apply(word: String): Stem = {
val stem: List[Char] = word.toLowerCase.trim.toList.sorted
new Stem(stem)
}
}
case class Stem private(stem: List[Char])(Map.empty[Stem, Set[String]] /: words) {
case (map, word) => map + (Stem(word) -> Set(word))
}words.map(word => Map(Stem(word) -> Set(word))) reduceLeft { _|+|_ }Context
StackExchange Code Review Q#15437, answer score: 14
Revisions (0)
No revisions yet.