【问题标题】:Convert list to a map with key being an index in Scala将列表转换为映射,其中键是 Scala 中的索引
【发布时间】:2017-05-12 16:15:53
【问题描述】:

我有一个字符串列表

val list = List("a", "b", "c", "d", "e")

我想要一个带有键的地图作为列表中项目的索引。所以我做了以下事情:

def mapByIndexes(list: List[String]): Map[Int, String] = (1 to list.size).zip(list).toMap

但是,生成的地图不保留索引顺序,结果我得到了这个:

Map(5 -> "e", 1 -> "a", 2 -> "b", 3 -> "c", 4 -> "d") 

如何修改上面的代码,以便获得具有以下自然顺序的地图?

Map(1 -> "a", 2 -> "b", 3 -> "c", 4 -> "d", 5 -> "e") 

注意:我知道我可以对生成的地图进行排序,但我可以避免该步骤并创建一个已经保留顺序的地图吗?

编辑:Scala LinkedHashMap.toMap preserves order? 中描述的ListMap 解决方案有效,但我不喜欢额外的括号和_* 这么简单的事情。没有别的东西,所以我可以有一个链接?如果没有,我会接受@pamu 的回答。

【问题讨论】:

标签: scala list dictionary scala-collections


【解决方案1】:

我知道我可以对生成的地图进行排序

不,你不能。对Map 进行排序没有意义。但是有Map 实现以自然顺序存储密钥,例如TreeMapIntMap 也可以,IIRC)。请注意,它与保留插入顺序相同,就像 ListMapLinkedHashMap 所做的那样。

Scala LinkedHashMap.toMap 中描述的 ListMap 解决方案保留了顺序?工作,但我不喜欢额外的括号和 _* 这么简单的事情。是不是没有别的东西了,所以我只能有一个链接?

不(至少,我不这么认为),但您可以轻松定义它:

implicit class ToListMap[A, B](x: Seq[(A, B)]) {
  def toListMap = ListMap(x: _*)
}

// somewhere where ToListMap is in scope or imported:
val list = List(1 -> 2, 3 -> 4)
list.toListMap

请注意,ListMap 基本上是一个列表(顾名思义),因此在其中查找比任何合理的地图实现都慢。

当然,您可以对TreeMap 做同样的事情。

【讨论】:

  • 通过排序地图我的意思是你描述的东西。如果你用谷歌搜索“sort map scala”,它会显示这些:)
  • 顺便说一句,您提供的代码无法编译。我收到type mismatch; found : Seq[(A, B)] required: (?, ?) def toListMap = ListMap(x)
  • 嗨,Alexey - 你为什么不提SortedMap?它是否没有解决 OP 对按其键排序的 map 的需求?
  • @KevinMeredith 因为我已经提到了TreeMap,这是SortedMap的实现。
  • @KevinMeredith 如果你去scala.collection.immutable.SortedMap,你会发现它也是一个具有scala.collection.immutable.TreeMap作为子类的特征(尽管2.12还为两者添加了mutable对应物)。
【解决方案2】:

使用ListMap。压缩后而不是做toMap,只需构造保留元素顺序的ListMap。您可以使用其伴随对象构建 ListMap。它接受元组的 var args。

def mapByIndexes(list: List[String]): ListMap[Int, String] = ListMap((1 to list.size).zip(list): _*)

Scala REPL

scala> import scala.collection.immutable._
import scala.collection.immutable._

scala> def mapByIndexes(list: List[String]): ListMap[Int, String] = ListMap((1 to list.size).zip(list): _*)
mapByIndexes: (list: List[String])scala.collection.immutable.ListMap[Int,String]

scala> mapByIndexes(list)
res10: scala.collection.immutable.ListMap[Int,String] = Map(1 -> a, 2 -> b, 3 -> c, 4 -> d, 5 -> e)

【讨论】:

  • 很好,也适合我。我不喜欢额外的括号和_*。没有别的东西,所以我可以有一个简单的链接?
猜你喜欢
  • 2013-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-23
  • 1970-01-01
  • 2014-04-09
  • 1970-01-01
  • 2018-07-23
相关资源
最近更新 更多