2015-02-10 69 views
0

這裏是場景:只在某些特定情況下減少元素。如何在scala中實現部分縮減?

例如, val sen = List("Jone", "had", "a", "great", "time", "."),如果元素以「e」結尾,則將其與下一個元素連接起來。對於sen,結果可能是("Jone had", "a", "great", "time .")

是否有任何優雅的方式來實現這些,而不是一個循環?

+0

這是有點不清楚你問什麼。爲什麼在你的例子中,如果它包含'e'並且它們是連續的,''great''不與''time'串聯? – ale64bit 2015-02-10 02:41:12

+0

對不起,應該是結束了,已經更新。 – Tilney 2015-02-10 02:48:15

+0

類似'val x = List(「ae」,「be」,「ce」)'從你的觀點來看會減少什麼? – ale64bit 2015-02-10 02:57:04

回答

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

我不知道爲什麼,但我總是忘記foldLeft跟蹤的類型可能與列表類型不同。 +1 – 2015-02-10 03:23:44

+0

兩者都很棒。我仍然在Java風格編程scala ... – Tilney 2015-02-10 03:28:46

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 
+0

它確實工作!但我仍然需要更多時間來理解你的代碼。感謝您的解決方案! – Tilney 2015-02-10 03:08:58

+1

'case Nil => List(s); case head :: rest如果head頭帶着「e」=> head +「」+ s :: rest; case _ => s :: curList}'(只在多行上)也許? – 2015-02-10 13:55:33

+0

Yah,我正在優化,但是因爲它是一個香草,所以我過早地優化了.... – 2015-02-10 15:01:16