2012-02-20 17 views
7

Gente, He estado escribiendo código en Scala últimamente para enseñarme el idioma y en algunos experimentos recientes, he usado an NLP library to produce a set of part-of-speech tagged words a partir de la entrada de un usuario.Comprensión de la lista Scala de Idiomatic: primer elemento que coincide con

Quiero escribir una función que me da el primer verbo en la oración. Si no hay verbos, entonces quiero suponer que la primera palabra del conjunto es el verbo (por ejemplo, si el jugador acaba de escribir "quién" o "tiempo de actividad", mi juego los considera verbos).

El siguiente es un bloque de código tan feo que solo una madre podría amar, y apesta a una programación imperativa y quiero refactorizarlo en algo más parecido a Scala idiomático, idealmente algo que no tiene un solo "si" declaración en él.

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 
    } 
} 

Las "palabras" variable es de tipo ListBuffer [EnrichedWord], donde EnrichedWord es mi clase que contiene una parte del discurso (POS, contiene caso de objetos como verbo, sustantivo, etc) y la palabra original (valor)

Cualquier orientación que puedan proporcionar los genios de Scala al refaccionar este código tan feo sería fantástico.

+0

"... sólo una madre podría amar." –

+0

... solo una madre podría amar. "¡Mejor frase que he leído hoy! –

Respuesta

9

Este se encarga, además, el caso cuando words está vacía, probarlo:

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

Si está seguro de words nunca habrá un vacío Set, éste es más simple:

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

Por cierto, si estás usando HashSet la noción de que algún elemento sea el primero realmente no tiene sentido. Si cada elemento representa una palabra en una oración, debería haber sido List o Seq.

+0

Intenté tu primera opción contra un ListBuffer (tienes razón, Set no tiene sentido aquí) y obtuve: error: el mapa de valores no es miembro de ScalaObject con java.io.Serializable \t \t words.find (_. Pos == Verb) .getOrElse (words.headOption) .map (_. Value) –

+4

@KevinHoffman Luego reemplace 'getOrElse' con' orElse'. –

+0

@Jean -PhilippePellet: de hecho, gracias! Actualicé mi respuesta –

2

La versión (sin punto) canónica es probablemente:

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

Otra opción es:

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

Las palabras pueden estar vacías, por ejemplo, el jugador podría haber presionado enter y enviado un comando en blanco –

+0

@KevinHoffman - ¿Qué debería hacer el código en ese caso? –

+0

Si las palabras están vacías, Actualmente estoy volviendo "" como el primer verbo ... No me gusta pasar nulos por ahí ni me gusta hacer código descendente hacer comprobaciones Some/None. –

Cuestiones relacionadas