在Scala中的地图中比较2个值有更好还是更实用的方法吗? [英] Is there a better or functional way to compare 2 values in a map in Scala?

查看:112
本文介绍了在Scala中的地图中比较2个值有更好还是更实用的方法吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些功能允许用户比较地图中包含的两个团队。包含在地图中的数据是从一个文本文件中读取的,该文件包含过去5个赛季关于橄榄球队及其积分记录的信息。数据存储为Map [String,List [Int]]:

 曼联,72,86,83,90, 94 
曼城,80,84,91,77,88
切尔西,76,85,92,87,84
阿森纳,70,79,81,76,83
利物浦,69,77,80,73,79

以下功能允许用户输入并且比较两队最近(最后)积分记录的差异。

  val teamdata = readTextFile (teams.txt)

//用户在键盘上按下2,这将调用调用compareTeams
菜单的CompareTeams def menuOptionTwo():Boolean = {
// 2 - 比较2个由用户选择的团队
menuCompareCompares(compareTeams)
true
}

//显示比较队列结果的函数
def menuCompareTeams(f: (String,String)=>((String,Int),(String,Int),String))= {
val input = f(readLine(Enter first team to compare>),
readLine(输入第二个球队比较>))
println(s| Team 1:$ {input._1._1} - Points:$ {input._1._2}
| Team 2:$ {input._2._1} - Points:$ {input._2._2}
| $ {input._3}。stripMargin)
}

///比较两个团队的函数 - 由menuCompareTeams调用
def compareTeams(team1:String,team2:String):((String,Int),(String,Int),String)= {
def lastPoints(list:List [Int]):Int = list match {
case Nil =>抛出新的异常(空列表)
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){
完成更高分的球队是:+ team1 +,他们上赛季的总得分是:+ team1Points +。+(team1Points-team2Points)+两队之间有点差距。
}
else if(team1Points == team2Points){
上赛季球队得分相同:+(team1Points | team2Points)
}
else {
完成更高的球队是:+ team2 +,他们上赛季的总得分是:+ team2Points +。+(team2Points-team1Points)+两点之间的差异队。


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

}
pre>

例如当用户输入曼联和曼城时的正确输出如下所示:


球队1:曼联 - 积分:94

第二组:曼城 - 积分:88



完成更高的球队是:曼联,他们上赛季的总得分是:94.两队的差距为6分。

是否有更好的或功能性的方法来执行我目前为2队比较所做的工作?



编辑:我已经根据Alex的建议编辑了这个问题。

解决方案 More Functional



您所遇到的一个副作用是抛出空名单。如果这确实是一种特殊情况,那么 lastPoints 应返回 尝试[Int] 。除此之外,你保持参照透明度,使用模式匹配,并使用递归函数,所以你不能获得更多功能。



更好 您可以使用 List# lastPoints (假设您不会抛出异常)而不是自己写:

  val lastPoints =(_:List [Int])。lastOption 

可以如下使用:

  val getPoints = 
(team:字符串)=> teamdata.get(team)
.flatMap(lastPoints)
.getOrElse(0)

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

总的来说,我总是在搜索一个收集方法来解决我的问题,然后试着拥有。依靠 lastOption flatMap getOrElse 虫子潜伏的地方更少。


I have functions which allow the user to compare two teams contained within a map. The data contained in the map is read in from a text file which contains information about football teams and their points tallies for the past 5 seasons. The data is stored as Map[String, List[Int]]:

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

The functions below allow the user to enter the names of two teams and compare the difference between the most recent (last) points tallies for the two teams.

 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)

 }

E.g. The correct output for when the user enters 'Manchester United' and 'Manchester City' is shown below:

Team 1: Manchester United - Points: 94

Team 2: Manchester City - Points: 88

The team who finished higher is: Manchester United, their total points tally for last season was: 94. There was a difference of 6 points between the two teams.

Is there a better or functional way to do what I am currently doing for the comparison of 2 teams?

EDIT: I have edited the question based on Alex's suggestion.

解决方案

"More Functional"

The one "side effect" you do have is throwing an exception for empty lists. If that is truly an exceptional case then lastPoints should return a Try[Int]. Other than that you maintain referential transparency, use pattern matching, and use recursive functions so you can't get "more functional".

"Better"

You could use List#lastOption in lastPoints (assuming you don't throw exceptions) instead of writing your own:

val lastPoints = (_ : List[Int]).lastOption

Which could then be used as follows:

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

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

In general, I always go searching for a collection method that solves my problem before trying to "roll my own". By relying on lastOption, flatMap, and getOrElse there are fewer places for bugs to lurk.

这篇关于在Scala中的地图中比较2个值有更好还是更实用的方法吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆