如何在scala中实现部分reduce?

时间:2015-02-10 02:37:40

标签: scala

以下是场景:仅在某些特定情况下减少元素。

EG。 val sen = List("Jone", "had", "a", "great", "time", "."),如果元素以“e”结尾,则将其与下一个元素连接起来。对于sen,结果可能是("Jone had", "a", "great", "time .")

有没有优雅的方法来实现这些而不是循环?

2 个答案:

答案 0 :(得分:4)

您可以简单地使用foldLeft,如下所示:

val result = sen.foldLeft(List[String]()) {
    (rs, s) => 
      if (rs.nonEmpty && rs.head.endsWith("e")) 
        (rs.head + " " + s) :: rs.tail 
      else 
        s :: rs
  }.reverse

只需用您自己的功能替换rs.head.endsWith("e")

答案 1 :(得分:2)

发布@kaktusito的foldLeft是最好的方法。以下是其工作方式的内部结构....大部分内容。

def partialReduce(list : List[String]): List[String] = {
  @scala.annotation.tailrec
  def internalRecurse(previousWord: String)(reducedList: List[String], finalList: List[String]): List[String] = 
    reducedList match {
      case Nil => finalList :+ previousWord //No more words, just add the previous to the list and return
      case head :: rest => {
        //if ends with e, run through the rest with the new word being the old + the head
        if(previousWord endsWith "e") internalRecurse(previousWord + " " + head)(rest, finalList)
        //if doesn't end with e, append the previous word to the final list 
        //and run the rest with the head as the next to check
        else internalRecurse(head)(rest, finalList :+ previousWord)
      }
    }

  //Call the internal method only if there is at least one item in the list
  list match {
    case Nil => Nil
    case head :: rest => internalRecurse(head)(rest, List())
  }
}

此外,我将发布我的模式匹配版本,因为我更喜欢它的外观:

val result = sen.foldLeft(List[String]()) {
    (curList, s) => {
       curList match {
         case Nil => List(s)
         case head :: rest => {
           if(head endsWith "e") head + " " + s :: rest
           else s :: curList
         }
       }
    }   
  }.reverse