0

Nim has OrderedTable how can I get the element by its index, and not by its key?

If it's possible - is this an efficient operation, like O(log n) or better?

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

Something like

map.getByIndex(1) # No such method

P.S.

I'm currently using both seq and Table to provide both key and indexed access and wonder if it could be replaced by OrderedTable

type IndexedMap = ref object
  list*: seq[float]
  map*:  Table[string, float]
Alex Craft
  • 13,598
  • 11
  • 69
  • 133

1 Answers1

1

There is no direct index access to ordered tables because of their internal structure. The typical way to access the elements in order is:

import tables

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

for f in map.keys:
  echo $f

Basically, accessing the keys iterator. If you click through the source link in the documentation, you reach the actual iterator code:

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

And if you follow the implementation of the forAllOrderedPairs template (it's recommended you are using an editor with jump to implementation capabilities to inspect such code easier):

  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

No idea about performance there, but it won't be as fast as accessing a simple list/array, because the internal structure of OrderedTable contains a hidden data field with the actual keys and values, and it requires an extra conditional check to verify that the entry is actually being used. This implementation detail is probably a compromise to avoid reshuffling the whole list after a single item deletion.

If your accesses are infrequent, using the iterator to find the value might be enough. If benchmarking shows it's a bottleneck you could try freezing the keys/values iterator into a local list and use that instead, as long as you don't want to mutate further the OrderedTable.

Or return to your original idea of keeping a separate list.

Grzegorz Adam Hankiewicz
  • 7,349
  • 1
  • 36
  • 78