2017-01-05 1 views
0

私はマップ内に含まれる2つのチームを比較する機能を持っています。地図に含まれるデータは、過去5年間のフットボールチームとそのポイントの情報に関するテキストファイルから読み込まれます。Scalaの地図で2つの値を比較する方が優れているか機能的な方法がありますか?

Manchester United, 72, 86, 83, 90, 94 
Manchester City, 80, 84, 91, 77, 88 
Chelsea, 76, 85, 92, 87, 84 
Arsenal, 70, 79, 81, 76, 83 
Liverpool, 69, 77, 80, 73, 79 

の機能は以下のユーザーがために集計ポイント2つのチームの名前を入力し、直近の間(最後の)違いを比較することができます。データは地図[文字列、リスト[INT]]として保存されています2つのチーム。

val teamdata = readTextFile("teams.txt") 

//User presses 2 on keyboard, this invokes menuCompareTeams which invokes compareTeams 
def menuOptionTwo(): Boolean = { 
    //2 - compare 2 teams selected by the user 
    menuCompareTeams(compareTeams) 
    true 
} 

//Function which displays the results of compareTeams 
def menuCompareTeams(f: (String, String) => ((String, Int), (String, Int), String)) = { 
     val input = f(readLine("Enter first team to compare>"), 
         readLine("Enter second team to compare>")) 
     println(s"""|Team 1: ${input._1._1} - Points: ${input._1._2} 
        |Team 2: ${input._2._1} - Points: ${input._2._2} 
        |${input._3}""".stripMargin)   
} 

///Function which compares the 2 teams - invoked by menuCompareTeams 
def compareTeams(team1: String, team2: String): ((String, Int), (String, Int), String) = { 
    def lastPoints(list: List[Int]): Int = list match { 
    case Nil => throw new Exception("Empty list") 
    case h :: Nil => h 
    case _ :: tail => lastPoints(tail) 
    } 

    val team1Points = teamdata.get(team1) match{ 
    case Some(p) => lastPoints(p) 
    case None => 0 
    } 

    val team2Points = teamdata.get(team2) match{ 
    case Some(p) => lastPoints(p) 
    case None => 0 
    } 

    val pointsComparison = if(team1Points > team2Points){ 
    "The team who finished higher is: " + team1 + ", their total points tally for last season was: " + team1Points + ". There was a difference of " + (team1Points-team2Points) + " points between the two teams." 
    } 
    else if(team1Points == team2Points){ 
    "The teams had equal points last season: " + (team1Points|team2Points) 
    } 
    else{ 
    "The team who finished higher is: " + team2 + ", their total points tally for last season was: " + team2Points + ". There was a difference of " + (team2Points-team1Points) + " points between the two teams." 
    } 

    ((team1, team1Points), (team2, team2Points), pointsComparison) 

} 

など。ユーザーが「マンチェスター・ユナイテッド」と「マンチェスター・シティ」を入力したときの正しい出力を以下に示します。

チーム1:マンチェスター・ユナイテッド - ポイント:94

チーム2:マンチェスター・シティ - ポイント:88

マンチェスター・ユナイテッドを上回ったチームは、昨シーズンの総合得点は94であった。両チームの間に6ポイントの差があった。

私は現在2つのチームの比較のために現在行っていることを行うためのより良いまたは機能的な方法がありますか?

EDIT:アレックスの提案に基づいて質問を編集しました。

+0

複数の質問の非常に長いテキスト。私はそれを複数の質問に分割するように提案したいと思います。基本から始めましょう:シーズンの結果に基づいて2つのチームを比較する方がどうでしょうか。 –

+0

@AlexFruzenshteinフィードバックのおかげで、私はあなたの提案に基づいて質問を編集しました。 – ASGD

答えて

0

「より機能」あなたが持っているん

1「副作用」は空のリストのための例外をスローしています。それが本当に例外的な場合は、lastPointsTry[Int]を返します。それ以外の場合は、参照の透過性を維持し、パターンマッチングを使用し、再帰関数を使用して「より機能的」にすることはできません。

あなたが代わりにあなた自身を書くのlastPointsList#lastOption(あなたが例外をスローしないと仮定)を使用することができ

"ベター":

次のように使用することができ
val lastPoints = (_ : List[Int]).lastOption 

val getPoints = 
    (team : String) => teamdata.get(team) 
          .flatMap(lastPoints) 
          .getOrElse(0) 

val team1Points = getPoints(team1) 
val team2Points = getPoints(team2) 

一般に、私はいつも私の問題を解決するコレクションメソッドを探します問題を "自分自身をロールバック"しようとする前に。 lastOptionflatMap、およびgetOrElseに依存することで、バグが潜んでいる場所が少なくなります。

関連する問題