【问题标题】:max function on list do not work in scala?列表中的 max 函数在 scala 中不起作用?
【发布时间】:2015-03-28 04:55:00
【问题描述】:

有一个scala代码的sn-p,我觉得很简单

val m1 = Map("age"->60,"name"->"x")
val m2 = Map("age"->99,"name"->"j")
val l = List(m1,m2)
val max = l.maxBy(_("age"))

但是,而不是预期的结果 val m2 = Map("年龄"->99,"姓名"->"j") 我收到一个错误:

<console>:13: error: No implicit Ordering defined for Any.

我知道隐式参数有问题,但我不知道如何解决这个问题。

更新 此外,假设我需要一个更通用的解决方案,一个函数

def max(l:List[Map[String,Any]],key:String)

那么 max(l,"age") == Map("age"->99,"name"->"j") max(l,"name") == Map("age"->60,"name"->"x")

【问题讨论】:

    标签: scala


    【解决方案1】:

    您的地图具有 Map[String, Any] 类型,因此编译器无法为 Any 对象找到 Ordering。添加对Int的显式转换:

    val max = l.maxBy(_("age").asInstanceOf[Int])
    

    或者尝试将Map 与特定值的类型一起使用,例如Map[String, Int] 或类似的。

    其他方式是使用case classestuples

    val list = List((60, "j"), (99, "x"))
    list.maxBy(_._1)
    

    【讨论】:

    • 类型转换在 scala 中看起来有点“邪恶”
    • @JadeTang:初始代码是邪恶的。您应该使用自定义类而不是 Map。例如,您可以使用带有鸭子类型的匿名类:val m1 = new { val age = 60; val name = "j" }; ...; l.maxBy( _.age ).name
    【解决方案2】:

    这行得通,

    l.maxBy(m => m("age").toString.toInt)
    

    并且更接近最​​大(数字)年龄的预期语义,即使它不能证明类型安全,原始地图类型也不保留有关预期类型的​​信息,如前所述。

    【讨论】:

      【解决方案3】:

      尝试使用最后一行作为 val max = l.maxBy(_("age").toString.toInt)

      【讨论】:

      • 由于"11" &gt; "2",您不能按字符串排序,在进行比较之前您需要转换为Int
      • @Lee -> 谢谢我忘了补充。 :)
      【解决方案4】:

      这样的事情可能会奏效(不是我喜欢Map[String, Any] 的想法):

      def myOrder(k: String) = { 
        x: Map[String, Any] => 
          x(k) match { case i:Int => (i, "") 
                       case s:String => (0, s) } 
      }
      
      l.maxBy(myOrder("age")) // Map(age -> 99, name -> j)
      l.maxBy(myOrder("name")) // Map(age -> 60, name -> x)
      

      【讨论】:

      • Map[String, Any] 似乎是个坏主意,但我确实需要一个地图来存储不同类型的值。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-30
      • 1970-01-01
      • 2014-06-07
      • 1970-01-01
      相关资源
      最近更新 更多