Scala:获取地图中元素的索引

Scala: Getting the index of an element in a Map

我有一个 Map[String, Object],其中的键是一个 ID。该 ID 现在在另一个对象中引用,我必须知道该 ID 具有的索引(地图中的位置)。我不敢相信没有 .indexOf 我怎样才能做到这一点?

我真的必须为自己构建一个包含所有键的列表或另一个具有 ID1 -> 1、ID2 -> 2 的 Map 吗? 我必须多次获取 ID 的索引。 List 或那个 Map 会更有效率吗?

根据定义,地图没有索引。

您可以枚举映射中的键,但这不能保证stable/repeatable。添加一个新元素,它可能会由于重新散列而随机更改每个其他元素的编号。如果你想要一个键到索引的稳定映射(或相反),你必须将这个映射存储在某个地方,例如通过将地图序列化为列表。

Map[A,B] 转换为有序集合,例如 Seq[(A,B)] 配备 indexOf 方法。注意

val m = Map("a" -> "x", "b" -> "y")

那个

m.toSeq
Seq[(String, String)] = ArrayBuffer((a,x), (b,y))

从上面的广泛讨论中可以看出,此转换不保证生成的有序集合中的任何特定顺序。这个集合可以根据需要进行排序。

或者,您可以索引映射中的键集,例如,

val idxm = for ( ((k,v),i) <- m.zipWithIndex ) yield ((k,i),v)
Map[(String, Int),String] = Map((a,0) -> x, (b,1) -> y)

其中等价于 indexOf 的地方例如

idxm.find { case ((_,i),v) => i == 1 }
Option[((String, Int), String)] = Some(((b,1),y))

@Dora,正如大家提到的那样,地图是无序的,因此无法就地索引它们并将 id 与它们一起存储。
很难猜测在地图中存储 (K,V) 对然后为每个 K 获取唯一 ID 的用例。因此,根据我的理解,这些是一些建议 -

1. 您可以使用 LinkedHashMap 而不是 Map ,这将保持插入顺序,因此您将获得稳定的迭代。在此地图上获取 KeysIterator 并将其转换为一个列表,该列表为您提供地图中每个键的唯一索引。像这样-

import scala.collection.mutable.LinkedHashMap
val myMap = LinkedHashMap("a"->11,  "b"->22, "c"->33)
val l = myMap.keysIterator.toList
l.indexOf("a") //get index of key a
myMap.+=("d"->44) //insert new element 
val l = myMap.keysIterator.toList
l.indexOf("a") //index of a still remains 0 due to linkedHashMap
l.indexOf("d") //get index of newly inserted element.

很明显,与HashMaps相比,在linkedHashMap中插入元素是昂贵的。
从 Map 中删除元素会自动将索引向左移动。

myMap.-=("b")
val l = myMap.keysIterator.toList
l.indexOf("c") // Index of "c" moves from 2 to 1.
  1. 将 (K->V) 映射到 (K->(index, v)) 并在插入新元素时手动生成索引。

    class ValueObject(val index: Int, val value: Int)
    val myMap = scala.collection.mutable.Map[String, ValueObject]()
    myMap.+=("a"-> new ValueObject(myMap.size+1, 11))
    myMap("a").index<br/> // get index of key a
    myMap.+=("b"-> new ValueObject(myMap.size+1, 22))
    myMap.+=("c"-> new ValueObject(myMap.size+1, 33))
    myMap("c").index<br/> // get index of key c
    myMap("b").index<br/> // get index of key b
    

如果我们需要没有间隙的索引,删除会很昂贵,因为我们需要相应地更新所有键。但是,键插入和搜索会更快。

如果我们确切地知道您需要什么,这个问题就可以得到有效解决,所以如果上述解决方案不适合您,请解释!!! (也许你真的不需要地图来解决你的问题)