如何从Nim的OrderedTable中通过索引获取元素?

问题描述

Nim有OrderedTable,如何才能通过其索引而不是其键来获取该元素?

如果可能-这是一种高效的操作,例如O(log n)还是更好的方法

import tables
let map = {"a": 1,"b": 2,"c": 3}.toOrderedTable

类似

map.getByIndex(1) # No such method

P.S。

我目前同时使用seqTable来提供密钥访问和索引访问,并想知道是否可以用OrderedTable代替它

type IndexedMap = ref object
  list*: seq[float]
  maP*:  Table[string,float]

解决方法

由于其内部结构,因此无法直接访问有序表。按顺序访问元素的典型方法是:

import tables

let map = {"a": 1,"b": 2,"c": 3}.toOrderedTable

for f in map.keys:
  echo $f

基本上,访问keys iterator。如果您点击文档中的 source 链接,则会到达the actual iterator code

  let L = len(t)
  forAllOrderedPairs:
    yield t.data[h].key

如果您遵循the implementation of the forAllOrderedPairs template(建议您使用具有跳转到实现功能的编辑器来更容易地检查此类代码):

  if t.counter > 0:
    var h = t.first
    while h >= 0:
      var nxt = t.data[h].next
      if isFilled(t.data[h].hcode):
        yieldStmt
      h = nxt

不知道那里的性能,但是它不如访问简单的列表/数组快,因为OrderedTable的内部结构包含一个隐藏的data字段,其中包含实际的键和值,并且需要进行额外的条件检查,以验证该条目是否正在实际使用中。为了避免在删除单个项目后重新整理整个列表,此实现细节可能是一个折衷方案。

如果您的访问很少,那么使用迭代器查找值可能就足够了。如果基准测试显示它是瓶颈,那么您可以尝试冻结键/值迭代器到本地列表中,并使用它,只要您不希望进一步突变OrderedTable

或返回保留单独列表的原始想法。