【问题标题】:Scala HashMap from an Array来自数组的 Scala HashMap
【发布时间】:2017-03-19 11:36:37
【问题描述】:

我有一个这样的 2 元组 Scala 数组:

(("A", "2015-11-01"), ("B", "2016-11-11"), ("A", "2017-11-01"), ("B", "2013-11-11"))

我想创建一个映射,其中键映射到最新日期。所以,在上面的例子中,结果应该是:

Map ("A" -> "2017-11-01", "B" -> "2016-11-11")

我知道如何迭代地执行此操作 - 但是 Scala 方式(功能方式)可以做到这一点吗?

【问题讨论】:

  • 您是否已经尝试过?你遇到了什么问题?

标签: java scala scala-collections scalatest


【解决方案1】:

首先 groupBy 键,然后选择最新的 Date。

arr
  .groupBy(_._1)
  .map { case (k, v) => k -> v.maxBy(_._2)._2 }

使用mapValues 使其更短

arr.groupBy(_._1).mapValues(_.maxBy(_._2)._2)

由于日期(字符串)格式正确,最大日期是最新日期。您无需将日期转换为以毫秒为单位的时间来确定最大日期。

Scala REPL

scala> val arr = Array(("A", "2015-11-01"), ("B", "2016-11-11"), ("A", "2017-11-01"), ("B", "2013-11-11"))
arr: Array[(String, String)] = Array((A,2015-11-01), (B,2016-11-11), (A,2017-11-01), (B,2013-11-11))

scala> :paste
// Entering paste mode (ctrl-D to finish)

arr
  .groupBy(_._1)
  .map { case (k, v) => k -> v.maxBy(_._2)._2 }


// Exiting paste mode, now interpreting.

res0: scala.collection.immutable.Map[String,String] = Map(A -> 2017-11-01, B -> 2016-11-11)

不需要日期转换,但如果您想转换,请继续。

日期转换:

//ensure correct date format is given to this method if not it will throw match error at runtime.
def convertStringDateToMillis(str: String): Long = {
 val regex = "(\\d{4})-(\\d{2})-(\\d{2})".r.unanchored
 val regex(year, month, day) = str
 val calendar = Calendar.getInstance()
 calendar.clear()
 calendar.set(Calendar.MONTH, month.toInt)
 calendar.set(Calendar.YEAR, year.toInt)
 calendar.set(Calendar.DAY_OF_MONTH, month.toInt)
 calendar.getTimeInMillis();
}

解决方案:

val arr = Array(("A", "2015-11-01"), ("B", "2016-11-11"), ("A", "2017-11-01"), ("B", "2013-11-11"))

arr.groupBy(_._1).map { case (k, v) => k -> v.maxBy(convertStringDateToMillis(_._2))._2 }

Scala REPL

scala> def convertStringDateToMillis(str: String): Long = {
     |  val regex = "(\\d{4})-(\\d{2})-(\\d{2})".r.unanchored
     |  val regex(year, month, day) = str
     |  val calendar = Calendar.getInstance()
     |  calendar.clear()
     |  calendar.set(Calendar.MONTH, month.toInt)
     |  calendar.set(Calendar.YEAR, year.toInt)
     |  calendar.set(Calendar.DAY_OF_MONTH, month.toInt)
     |  calendar.getTimeInMillis();
     | }
convertStringDateToMillis: (str: String)Long

scala> val arr = Array(("A", "2015-11-01"), ("B", "2016-11-11"), ("A", "2017-11-01"), ("B", "2013-11-11"))
arr: Array[(String, String)] = Array((A,2015-11-01), (B,2016-11-11), (A,2017-11-01), (B,2013-11-11))


scala> arr.groupBy(_._1).map { case (k, v) => k -> v.maxBy(x => convertStringDateToMillis(x._2))._2 }
res3: scala.collection.immutable.Map[String,String] = Map(A -> 2017-11-01, B -> 2016-11-11)

【讨论】:

  • 当我执行“arr.groupBy(_._1)”时,它抱怨“_1”部分并说“值_1 不是具有可序列化的产品的成员”。 “arr”的类型是 ArrayBuffer.. 所以,我在调用 groupBy 函数之前做了一个“arr.toArray”,但我仍然看到这个错误。谢谢。
  • @Darth.Vader .. 你的数组应该是这个val arr = Array(("A", "2015-11-01"), ("B", "2016-11-11"), ("A", "2017-11-01"), ("B", "2013-11-11"))
  • 我的 arr 变量如下所示:Array((A, 2015-11-01), (B, 2016-11-11), (A, 2017-11-01), (B, 2013-11-11))
【解决方案2】:

这样的事情应该可以工作:

array
  .groupBy(_._1)
  .mapValues(_.map(_._2).max)

【讨论】:

    猜你喜欢
    • 2012-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-25
    • 2015-09-26
    • 1970-01-01
    • 2015-10-19
    相关资源
    最近更新 更多