Scala:获取Map中元素的索引

时间:2015-12-08 15:12:48

标签: scala dictionary indexing data-retrieval

我有Map[String, Object],其中密钥是ID。该ID现在在另一个对象中引用,我必须知道该ID具有哪个索引(Map中的哪个位置)。我无法相信没有.indexOf 我怎么能做到这一点?

我是否真的必须使用所有键或其他具有ID1的地图构建自己的列表 - > 1,ID2 - > 2,...? 我必须多次获取ID的索引。 List或该地图会更有效吗?

3 个答案:

答案 0 :(得分:1)

@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
    
  2. 如果我们需要没有间隙的索引,那么

    删除会很昂贵,因为我们需要相应地更新所有密钥。但是,键插入和搜索会更快。

    如果我们确切知道您需要什么,这个问题可以有效解决,请解释上述解决方案是否对您不起作用! (可能你真的不需要地图来解决你的问题)

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

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))