问题描述
Nim有OrderedTable
,如何才能通过其索引而不是其键来获取该元素?
如果可能-这是一种高效的操作,例如O(log n)
还是更好的方法?
import tables
let map = {"a": 1,"b": 2,"c": 3}.toOrderedTable
类似
map.getByIndex(1) # No such method
P.S。
我目前同时使用seq
和Table
来提供密钥访问和索引访问,并想知道是否可以用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
。
或返回保留单独列表的原始想法。