【问题标题】:Scala How do you sort a map that has a String, with numbers in itScala 如何对包含字符串的地图进行排序,其中包含数字
【发布时间】:2020-06-12 23:22:34
【问题描述】:

我正在尝试通过获取字符串并使用字符串中的数字进行排序来对 mutable.Map[String, String] 进行排序。 输入:

"Liz", "Game: 2"
"Philip", "Game: 5"
"John", "Game: 0 | Score: 9"
"Kevin", "Game: None"

输出到这样的东西

"John", "Game: 5 | Score: 9"
"Liz", "Game: 2"
"Philip", "Game: 0"
"Kevin", "Game: None"

我试过这个https://alvinalexander.com/scala/how-to-sort-map-in-scala-key-value-sortby-sortwith/ 但它不符合我想要的排序 原谅我语法不好

【问题讨论】:

  • 地图是无序的集合,你为什么还要关心顺序?
  • @zolmukekni,您能否验证我的回答是否解决了您的问题?
  • 对不起,我忘记在输入和输出中指定一些东西,所以它会与你给我的答案不同。

标签: scala maps


【解决方案1】:

Scala 标准库知道如何对相同类型配置文件的元组进行排序,只要所有内部元素都可以排序。

只要选项元素可以排序,它也知道如何排序选项。

Float 值可以排序。

因此,您可以按内部 IntFloat 值对您的 String 进行排序,这些值可能存在或不存在,方法是将它们填充到 Option[Float] 元素的元组中。

import scala.util.Try

val games =
  scala.collection.mutable.Map("Liz"  -> "Game: 2"
                              ,"John" -> "Game: 0 | Score: 9"
                              ,"Philip" -> "Game: 5"
                              ,"Kevin"  -> "Game: None")
games.put("Jo", "Game: 11 | Score 0")

val numRE = "\\d*\\.?\\d+".r

games.toList.sortBy { case (_, str) =>
  val ns = numRE.findAllIn(str)
                .flatMap(n => Try(n.toFloat).toOption)
                .toVector
  (ns.lift(0), ns.lift(1))
}.reverse
//res1: List[(String, String)] = List((Jo,Game: 11 | Score 0)
//                                  , (Philip,Game: 5)
//                                  , (Liz,Game: 2)
//                                  , (John,Game: 0 | Score: 9)
//                                  , (Kevin,Game: None))

【讨论】:

  • 我使用可变映射来 .put 数据并尝试从那里排序,它不会排序,也不会在我将其转换为不可变映射时进行排序。它只有在像价值游戏一样已经在地图中时才有效。
  • 用 gradle 2.11:101 完成
  • 发布的代码在 Scala 2.12.7 和 Scala 2.13.1 上进行了测试。它提供评论的结果。我建议您在尝试将其合并到现有代码库中之前将其粘贴到您的环境中以证明这一点。
  • 我试过你的代码并打印出来,games.foreach{i=> print(i)}:这里是结果 (Kevin,Game: None)(Philip,Game: 5)(Jo, Game: 11 | Score 0)(John,Game: 0 | Score: 9)(Liz,Game: 2) 我做错了吗?
  • 啊,我很笨,需要赋值。
【解决方案2】:

您需要从您的字符串中获取数字并将其转换为Integer,例如:

val map: Map[String, String] = Map(("Liz", "Game: 11"), ("Philip", "Game: 5"))
val order: ((String, String)) => Integer = { case (_ , p2) => p2.stripPrefix("Game: ").toInt }
map.toSeq
  .sortWith(order(_) > order(_))
  .toList

【讨论】:

  • 我忘了添加这个,但是如果地图也有不同的数据,例如“Kevin”、“Score: 7”或“Mike”、“Score: 9 Wins:2”怎么办?那么工作呢?
  • @zolmukekni 那么您将需要以某种方式剥离所需的号码。您可以尝试为此使用正则表达式。
【解决方案3】:

样本数据:

scala> tmp
res19: scala.collection.mutable.Map[String,String] = Map(Philip -> Game: 0, John -> Game: 5, Liz -> Game: 2)

创建案例类:

case class someclass(name:String,score:Int,keyword:String)

将数据放入List[someClass]

val listOfScores = tmp.map(each => { 
  val name = each._1
  val keyword = each._2.split(":")(0)
  val score = each._2.split(":")(1).stripPrefix(" ").toInt
  someclass(name,score,keyword)
})

最后排序得到最终列表:

scala> listOfScores.toList.sortBy(_.score).reverse
res31: List[someclass] = List(someclass(A1,9,Goals), someclass(a2,5,Game), someclass(Liz,2,Game), someclass(John,0,Score), someclass(Philip,0,Game))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-07
    • 1970-01-01
    • 2021-04-28
    • 1970-01-01
    • 2020-02-18
    • 1970-01-01
    • 2023-02-03
    相关资源
    最近更新 更多