2016-10-05 44 views
1

我想統計每個雙字母的頻率。斯卡拉 - 火花字數,爲什麼滑動不工作

所以我寫了

val intputFile = "bible+shakes.nopunc" 
val sentences = sc.textFile(intputFile) 

val bigrams = sentences.map(sentence => sentence.trim.split(' ')).flatMap(wordList => 
    for (i <- List.range(0, (wordList.length - 2))) yield ((wordList(i), wordList(i + 1)), 1) 
) 

val bigrams2 = sentences.map(sentence => sentence.trim.split(' ')).flatMap(wordList => 
    wordList.sliding(2).map{case Array(x, y) => ((x,y), 1)} 
) 

而且他們似乎有相同的類型。

scala> bigrams 
res11: org.apache.spark.rdd.RDD[((String, String), Int)] = MapPartitionsRDD[7] at flatMap at <console>:28 

scala> bigrams2 
res12: org.apache.spark.rdd.RDD[((String, String), Int)] = MapPartitionsRDD[11] at flatMap at <console>:28 

階> bigrams.collect res15:數組[((字符串,字符串),智力)] =陣列(((聖,聖經),1),((聖經,授權),1), ((授權,國王),1),((國王,詹姆斯),1),((詹姆斯,版本),1),((version,textfile),1),((in,the),1), ((the,beginning),1),((beginning,god),1),((god,created),1),((created,the),1),((the,heaven),1), ((天,和),1),((和),1),((和),1),((地球),1),((地球,是),1), ((無),1),((無,形式),1),((形式和),1),((和void),1),((void,and),1), ((和,黑暗),1),((黑暗,是),1),((是,在),1),((在),1),((,),1), ((,),1),((of,the),1),((the,deep),1),((deep,and),1),((and,the),1), ((the,spirit),1),((spirit,of),1),((of,god),1),((god,moving),1),((move,upon),1), ((在,),1),((,,臉),1), ((...,1),((of,the),1),((and,god),1),((god),1),((...) ,當我這樣做時

scala> bigrams.collect 
res13: Array[((String, String), Int)] = Array(((holy,bible),1), ((bible,authorized),1), ((authorized,king),1), ((king,james),1), ((james,version),1), ((version,textfile),1), ((in,the),1), ((the,beginning),1), ((beginning,god),1), ((god,created),1), ((created,the),1), ((the,heaven),1), ((heaven,and),1), ((and,the),1), ((and,the),1), ((the,earth),1), ((earth,was),1), ((was,without),1), ((without,form),1), ((form,and),1), ((and,void),1), ((void,and),1), ((and,darkness),1), ((darkness,was),1), ((was,upon),1), ((upon,the),1), ((the,face),1), ((face,of),1), ((of,the),1), ((the,deep),1), ((deep,and),1), ((and,the),1), ((the,spirit),1), ((spirit,of),1), ((of,god),1), ((god,moved),1), ((moved,upon),1), ((upon,the),1), ((the,face),1), ((face,of),1), ((of,the),1), ((and,god),1), ((god,said),1), ((... 

scala> bigrams2.collect 
16/10/05 10:17:52 ERROR Executor: Exception in task 1.0 in stage 11.0 (TID 20) 
scala.MatchError: [Ljava.lang.String;@3224ea91 (of class [Ljava.lang.String;) 
    at $line27.$read$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$anonfun$2$$anonfun$apply$1.apply(<console>:29) 

bigrams2.take(5) 
res25: Array[((String, String), Int)] = Array(((holy,bible),1), ((bible,authorized),1), ((authorized,king),1), ((king,james),1), ((james,version),1)) 

評估它的第二種方法導致了一個錯誤。

爲什麼?如何解決它?我更喜歡第二種,確切的方式。

回答

0

的問題與您wordList.sliding(2).map{case Array(x, y) => ((x,y), 1){case Array(x, y) => ((x,y), 1)partial-function whcih只知道如何處理與該模式Array(x, y)相匹配的輸入。

因此,您的地圖將無法處理只有一個元素的窗口。你應該將其更改爲類似以下,

wordList.sliding(2).flatMap { 
    case Array(x, y) => Some((x, y), 1) 
    case _ => None 
} 

這裏,flatMap將壓平Option S.這樣確保結果只包含有效的雙向克。

+0

你應該提到一個'Option'可以被認爲是一個空的序列或者有一個項目 –

+1

@ShihaoXu實際上'Option'與序列不是空的或有1個項目相似。對於Scala初學者(或者函數式編程初學者)來說,解釋'Option'的實際定義是不可行的,所以人們告訴他們這樣想'Option'。您現在可以這樣想'Option',但請記住這不是真的。一旦你已經掌握了一個名爲'Monad'的函數式編程概念,你就會更好地理解'Option'。 –

0

你bigrams2表達有問題:

wordList.sliding(2).map{case Array(x, y) => ((x,y), 1)} 

地圖的情況下不處理的情況下的詞表中只有一個項目,這就是爲什麼你獲得MatchError。它表現爲句子哪個單詞。

要解決增加的情況下建設一個項目的數組:

wordList.sliding(2).map { 
    case Array(x, y) => ((x,y), 1) 
    case Array(x) => ??? 
}