Idiomatic Scala List Consrehension is the first item that matches

Folks, Recently, I wrote code in Scala to teach myself a language, and in some recent experiments, I used the NLP library to create a set of some words tagged with user input.

I want to write a function that gives me the first verb in a sentence. If there are no verbs, then I want to assume that the first word in the set is a verb (for example, if a player just typed โ€œwhoโ€ or โ€œuptimeโ€, this is considered a verb in my game).

The next block of code is so ugly that only a mother can love, and it stinks of imperative programming, and I want to reorganize it into something more like an idiomatic Scala, ideally something that doesn't have a single โ€œifโ€ in it.

def firstVerb = { if (words.size == 1) words.head.value else { val outWords = words.filter( word => word.pos == Verb) if (outWords == Set.empty) words.head.value else outWords.head.value } } 

The variable "words" is of type ListBuffer [EnrichedWord], where EnrichedWord is my class that contains a part of speech (pos, contains case objects such as Verb, Noun, etc.) and the source word (value).

Any guidance you can offer Scala geniuses on refactoring this ugly code butt will be fantastic.

+7
source share
2 answers

This additionally handles the case when words empty, try:

 words.find(_.pos == Verb).orElse(words.headOption).map(_.value).getOrElse("") 

If you are sure that words will never be an empty Set , this is simpler:

 words.find(_.pos == Verb).getOrElse(words.head).value 

BTW, if you use a HashSet , the notion that some element is the first does not really make sense. If each element represents a word in the message, it must be List or Seq .

+9
source

Perhaps the canonical version (without dots):

 words find(_.pos == Verb) orElse words.headOption map _.value getOrElse "" 

Another variant:

 (words.find(_.pos == Verb) ++ words.take(1)).take(1).map(_.value).mkString 
+2
source

All Articles