Scala Learning on Coursera Week3: TweetSet Class

Week3: TweetSet Class

最近一直在跟Coursera上的scala和cloud computing課斑唬,干脆開(kāi)博客記錄一下遇到的問(wèn)題和解決方法善炫。Scala作為函數(shù)式編程例隆,如何熟練掌握f(shuō)unction的傳遞佃牛,tail recursion的設(shè)計(jì)是這門課前半部分的重點(diǎn)她按。這次的作業(yè)是設(shè)計(jì)一個(gè)TweetSet阔挠,Tweet是一個(gè)記錄了user,string,Retweeted三個(gè)field的class飘庄,要求TweetSet以binary tree形式存儲(chǔ),同時(shí)滿足特定函數(shù)购撼。

Aim: To implement a TweetSet Class, including its fundamental functions.Eg: union, filter(p: Tweet => Boolean), mostRetweeted, descendingByRetweet

Note:
filter and mostRetweeted are both implemented using tail recursion(filterAcc and mostAcc)
注意tail recursion的邏輯跪削,一般都需要傳遞一個(gè)中間結(jié)果(1作為累加值或者2作為比較值),從而使下次遞歸可以直接比較之前完成部分的結(jié)果迂求。注意遞歸順序碾盐,這里因?yàn)槭莃inary tree,一般都是先elem揩局,再left毫玖,最后right。
filterAcc records a TweetSet acc that represents the accumulative tweetSet which satisfy the predicate pif (p(elem)) then include current tweet into the tweetSet
mostAcc records a tweet object with maximum retweets. At beginning, it is initialized as new tweet("ini","ini",0)retweet number is 0 at first!

Difficulties:
Remember how to use function to implement traverse of the list!!! Just as follows.
google.exists(x => y.text.contains(x))

val google = List("android", "Android", "galaxy", "Galaxy", "nexus", "Nexus")
val apple = List("ios", "iOS", "iphone", "iPhone", "ipad", "iPad")lazy 
val googleTweets: TweetSet = TweetReader.allTweets.filter(y => google.exists(x => y.text.contains(x)))lazy 
val appleTweets: TweetSet = TweetReader.allTweets.filter(y => apple.exists(x => y.text.contains(x)))

----------Codes-------------

package objsets

import TweetReader._

/**
 * A class to represent tweets.
 */
class Tweet(val user: String, val text: String, val retweets: Int) {
  override def toString: String =
    "User: " + user + "\n" +
    "Text: " + text + " [" + retweets + "]"
}

/**
 * This represents a set of objects of type `Tweet` in the form of a binary search
 * tree. Every branch in the tree has two children (two `TweetSet`s). There is an
 * invariant which always holds: for every branch `b`, all elements in the left
 * subtree are smaller than the tweet at `b`. The elements in the right subtree are
 * larger.
 *
 * Note that the above structure requires us to be able to compare two tweets (we
 * need to be able to say which of two tweets is larger, or if they are equal). In
 * this implementation, the equality / order of tweets is based on the tweet's text
 * (see `def incl`). Hence, a `TweetSet` could not contain two tweets with the same
 * text from different users.
 *
 *
 * The advantage of representing sets as binary search trees is that the elements
 * of the set can be found quickly. If you want to learn more you can take a look
 * at the Wikipedia page [1], but this is not necessary in order to solve this
 * assignment.
 *
 * [1] http://en.wikipedia.org/wiki/Binary_search_tree
 */
abstract class TweetSet {

  /**
   * This method takes a predicate and returns a subset of all the elements
   * in the original set for which the predicate is true.
   *
   * Question: Can we implment this method here, or should it remain abstract
   * and be implemented in the subclasses?
   */
    def filter(p: Tweet => Boolean): TweetSet =
      this.filterAcc(p, new Empty())
  
  /**
   * This is a helper method for `filter` that propagetes the accumulated tweets.
   */
  def filterAcc(p: Tweet => Boolean, acc: TweetSet): TweetSet

  /**
   * Returns a new `TweetSet` that is the union of `TweetSet`s `this` and `that`.
   *
   * Question: Should we implment this method here, or should it remain abstract
   * and be implemented in the subclasses?
   */
    def union(that: TweetSet): TweetSet 
  
  /**
   * Returns the tweet from this set which has the greatest retweet count.
   *
   * Calling `mostRetweeted` on an empty set should throw an exception of
   * type `java.util.NoSuchElementException`.
   *
   * Question: Should we implment this method here, or should it remain abstract
   * and be implemented in the subclasses?
   */
    def mostRetweeted: Tweet = mostAcc(new Tweet("ini_max", "ini_max", 0))
    def mostAcc(max: Tweet): Tweet
  
  /**
   * Returns a list containing all tweets of this set, sorted by retweet count
   * in descending order. In other words, the head of the resulting list should
   * have the highest retweet count.
   *
   * Hint: the method `remove` on TweetSet will be very useful.
   * Question: Should we implment this method here, or should it remain abstract
   * and be implemented in the subclasses?
   */
    def descendingByRetweet: TweetList 
  
  /**
   * The following methods are already implemented
   */

  /**
   * Returns a new `TweetSet` which contains all elements of this set, and the
   * the new element `tweet` in case it does not already exist in this set.
   *
   * If `this.contains(tweet)`, the current set is returned.
   */
  def incl(tweet: Tweet): TweetSet

  /**
   * Returns a new `TweetSet` which excludes `tweet`.
   */
  def remove(tweet: Tweet): TweetSet

  /**
   * Tests if `tweet` exists in this `TweetSet`.
   */
  def contains(tweet: Tweet): Boolean

  /**
   * This method takes a function and applies it to every element in the set.
   */
  def foreach(f: Tweet => Unit): Unit
}

class Empty extends TweetSet {
    def filterAcc(p: Tweet => Boolean, acc: TweetSet): TweetSet = acc
    
    def union(that: TweetSet): TweetSet = that
    
    def mostAcc(max: Tweet): Tweet = max
    
     def descendingByRetweet: TweetList = Nil
  
  /**
   * The following methods are already implemented
   */

  def contains(tweet: Tweet): Boolean = false

  def incl(tweet: Tweet): TweetSet = new NonEmpty(tweet, new Empty, new Empty)

  def remove(tweet: Tweet): TweetSet = this

  def foreach(f: Tweet => Unit): Unit = ()
}

class NonEmpty(elem: Tweet, left: TweetSet, right: TweetSet) extends TweetSet {

    def filterAcc(p: Tweet => Boolean, acc: TweetSet): TweetSet = 
      if  (p(elem)) right.filterAcc(p, left.filterAcc(p, acc.incl(elem)))
      else  right.filterAcc(p, left.filterAcc(p, acc))
  
    def union(that: TweetSet): TweetSet = 
      ((left union right) union that) incl elem
      
       def mostAcc(max: Tweet): Tweet = 
         if (elem.retweets > max.retweets) right.mostAcc(left.mostAcc(elem)) 
         else right.mostAcc(left.mostAcc(max)) 
    
    def descendingByRetweet: TweetList = 
      new Cons(this.mostRetweeted, this.remove(this.mostRetweeted).descendingByRetweet)
      
         
  /**
   * The following methods are already implemented
   */

  def contains(x: Tweet): Boolean =
    if (x.text < elem.text) left.contains(x)
    else if (elem.text < x.text) right.contains(x)
    else true

  def incl(x: Tweet): TweetSet = {
    if (x.text < elem.text) new NonEmpty(elem, left.incl(x), right)
    else if (elem.text < x.text) new NonEmpty(elem, left, right.incl(x))
    else this
  }

  def remove(tw: Tweet): TweetSet =
    if (tw.text < elem.text) new NonEmpty(elem, left.remove(tw), right)
    else if (elem.text < tw.text) new NonEmpty(elem, left, right.remove(tw))
    else left.union(right)

  def foreach(f: Tweet => Unit): Unit = {
    f(elem)
    left.foreach(f)
    right.foreach(f)
  }
}

trait TweetList {
  def head: Tweet
  def tail: TweetList
  def isEmpty: Boolean
  def foreach(f: Tweet => Unit): Unit =
    if (!isEmpty) {
      f(head)
      tail.foreach(f)
    }
}

object Nil extends TweetList {
  def head = throw new java.util.NoSuchElementException("head of EmptyList")
  def tail = throw new java.util.NoSuchElementException("tail of EmptyList")
  def isEmpty = true
}

class Cons(val head: Tweet, val tail: TweetList) extends TweetList {
  def isEmpty = false
}


object GoogleVsApple {
  val google = List("android", "Android", "galaxy", "Galaxy", "nexus", "Nexus")
  val apple = List("ios", "iOS", "iphone", "iPhone", "ipad", "iPad")

    lazy val googleTweets: TweetSet = TweetReader.allTweets.filter(y => google.exists(x => y.text.contains(x)))
  lazy val appleTweets: TweetSet = TweetReader.allTweets.filter(y => apple.exists(x => y.text.contains(x)))
  
  /**
   * A list of all tweets mentioning a keyword from either apple or google,
   * sorted by the number of retweets.
   */
     lazy val trending: TweetList = (googleTweets.union(appleTweets)).descendingByRetweet
  }

object Main extends App {
  // Print the trending tweets
  GoogleVsApple.trending foreach println
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末谐腰,一起剝皮案震驚了整個(gè)濱河市孕豹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌十气,老刑警劉巖励背,帶你破解...
    沈念sama閱讀 217,907評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異砸西,居然都是意外死亡叶眉,警方通過(guò)查閱死者的電腦和手機(jī)址儒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)衅疙,“玉大人莲趣,你說(shuō)我怎么就攤上這事”ヒ纾” “怎么了喧伞?”我有些...
    開(kāi)封第一講書人閱讀 164,298評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)绩郎。 經(jīng)常有香客問(wèn)我潘鲫,道長(zhǎng),這世上最難降的妖魔是什么肋杖? 我笑而不...
    開(kāi)封第一講書人閱讀 58,586評(píng)論 1 293
  • 正文 為了忘掉前任溉仑,我火速辦了婚禮,結(jié)果婚禮上状植,老公的妹妹穿的比我還像新娘浊竟。我一直安慰自己,他們只是感情好津畸,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布振定。 她就那樣靜靜地躺著,像睡著了一般洼畅。 火紅的嫁衣襯著肌膚如雪吩案。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 51,488評(píng)論 1 302
  • 那天帝簇,我揣著相機(jī)與錄音徘郭,去河邊找鬼。 笑死丧肴,一個(gè)胖子當(dāng)著我的面吹牛残揉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播芋浮,決...
    沈念sama閱讀 40,275評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼抱环,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了纸巷?” 一聲冷哼從身側(cè)響起镇草,我...
    開(kāi)封第一講書人閱讀 39,176評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎瘤旨,沒(méi)想到半個(gè)月后梯啤,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,619評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡存哲,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評(píng)論 3 336
  • 正文 我和宋清朗相戀三年因宇,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了七婴。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,932評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡察滑,死狀恐怖打厘,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情贺辰,我是刑警寧澤户盯,帶...
    沈念sama閱讀 35,655評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站魂爪,受9級(jí)特大地震影響先舷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜滓侍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望牲芋。 院中可真熱鬧撩笆,春花似錦、人聲如沸缸浦。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,871評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)裂逐。三九已至歹鱼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間卜高,已是汗流浹背弥姻。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,994評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留掺涛,地道東北人庭敦。 一個(gè)月前我還...
    沈念sama閱讀 48,095評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像薪缆,于是被迫代替她去往敵國(guó)和親秧廉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 背景 一年多以前我在知乎上答了有關(guān)LeetCode的問(wèn)題, 分享了一些自己做題目的經(jīng)驗(yàn)拣帽。 張土汪:刷leetcod...
    土汪閱讀 12,744評(píng)論 0 33
  • 同學(xué)們把書合上疼电,我們接著講。 很多人應(yīng)該對(duì)這個(gè)方法有所了解减拭,之前面試很多人說(shuō)這個(gè)是什么iOS黑魔法蔽豺,還會(huì)拽詞。于是...
    穿山甲救蛇精閱讀 2,825評(píng)論 4 20
  • 風(fēng)塵仆仆峡谊,卻又馬不停蹄茫虽,趁著長(zhǎng)假的尾巴刊苍,趕赴徽州古城。 雖說(shuō)人山人海的擁堵景象年年長(zhǎng)假屢見(jiàn)不鮮濒析,卻也只有春節(jié)正什,還有...
    寧黛閱讀 296評(píng)論 1 1
  • 【讀經(jīng)】 王下3章 【金句】 以色列王說(shuō):“哀哉!耶和華招聚我們這三王号杏,乃要交在摩押人的手里婴氮。” (列王紀(jì)下 3:...
    chanor閱讀 1,379評(píng)論 0 0
  • 最美的是師院深秋 銀杏樹(shù)下?tīng)磕愕氖?寫滿故事的實(shí)驗(yàn)樓 陪你走過(guò)快樂(lè)春秋 圖書館前十指環(huán)扣 一起看那晚霞合流 教七偶...
    少壯需努力閱讀 242評(píng)論 2 1