【问题标题】:Scala - Sort a Map based on Tuple ValuesScala - 根据元组值对地图进行排序
【发布时间】:2014-12-14 05:52:26
【问题描述】:

我正在尝试根据值元组对地图进行排序

val data = Map("ip-11-254-25-225:9000"  -> (1, 1413669308124L), 
               "ip-11-232-145-172:9000" -> (0, 1413669141265L), 
               "ip-11-232-132-31:9000"  -> (0, 1413669128111L), 
               "ip-11-253-67-184:9000"  -> (0, 1413669134073L), 
               "ip-11-232-142-77:9000"  -> (0, 1413669139043L))

排序标准应该基于元组中的两个值

我试过了

SortedMap[String, (Long,Long)]() ++ data

但没有成功。

有人可以建议一种更好的方法,先在 tuple._1 上排序,然后在 tuple._2 上排序

【问题讨论】:

  • 使用 def sortWith(lt: (A, A) ⇒ Boolean): List[A]compareTo 函数来比较你的元组。
  • 请注意,SortedMap 是按键排序的,而不是按值排序的,所以无论如何它都不是你想要的
  • 您可以使用ListMapsortBy(_._2),如[this question] 接受的答案中所述。

标签: scala data-structures scala-collections scala-2.10 sortedmap


【解决方案1】:

一般可以选择元组中的哪个元素优先排序;考虑一下这个

data.toSeq.sortBy {case (k,(a,b)) => (k,a,b) }

case 模式中,我们提取(嵌套)元组的每个元素。在上面的表达式中,我们按键排序,然后按值元组中的第一个元素,然后是第二个。另一方面,这

data.toSeq.sortBy {case (k,(a,b)) => (k,b) }

将按值元组中的键和最后一个元素排序,而这个

data.toSeq.sortBy {case (k,(a,b)) => (a,b) }

根据地图的值;这个

data.toSeq.sortBy {case (k,(a,b)) => (b) }

将按值元组中的最后一个元素排序。

更新正如@Paul 有用地指出的那样,Map 不保留任何顺序,因此结果作为序列保留在这里。

【讨论】:

  • 地图没有顺序。所以 .toMap 丢弃了排序。尝试打印 .sortBy 的结果,然后打印最终地图 - 它们的顺序不同
  • @Paul 绝对是,非常感谢;请注意更新。
【解决方案2】:

这就是你要找的吗?

data.toVector.sortBy(_._2)

这将按值(元组)对条目进行排序,其中顺序取决于两个元组参数。元组的默认排序行为是先排序_1,然后再排序_2

Vector((2,1), (1,2), (1,3), (1,1)).sorted
// Vector((1,1), (1,2), (1,3), (2,1))

【讨论】:

    【解决方案3】:

    对元组进行排序

    首先请注意,如果您对元组集合进行排序,您将得到与预期相同的结果,即首先比较第一个项目,然后比较第二个项目。

    例如(a1, b1) > (a2, b2) 当且仅当(a1 > a2) || ((a1 == a2) && (b1 > b2))

    因此,为了获得对元组排序的预期结果,您无需执行任何操作。

    接下来就是如何根据值对map进行排序以及排序后如何保持顺序。

    map进行排序

    您可以使用ListsortBy 方法,然后使用有序数据结构来保留顺序,如下所示:

    new scala.collection.immutable.ListMap() ++ data.toList.sortBy(_._2)
    

    如果你在 Scala REPL 中运行它,你会得到以下结果:

    scala> new scala.collection.immutable.ListMap() ++ data.toList.sortBy(_._2)
    res3: scala.collection.immutable.ListMap[String,(Int, Long)] = Map(ip-11-232-132-31:9000 -> (0,1413669128111), ip-11-253-67-184:9000 -> (0,1413669134073), ip-11-232-142-77:9000 -> (0,1413669139043), ip-11-232-145-172:9000 -> (0,1413669141265), ip-11-254-25-225:9000 -> (1,1413669308124))
    

    如果您只是想对它们进行排序并遍历结果(即,如果您不需要 map 作为结果),您甚至不需要使用 ListMap

    【讨论】:

      猜你喜欢
      • 2018-05-12
      • 2015-11-07
      • 2011-09-26
      • 1970-01-01
      • 2020-01-03
      • 2013-10-31
      • 1970-01-01
      • 1970-01-01
      • 2021-10-07
      相关资源
      最近更新 更多