Keep Map insert order

Hi,

I’m looking for a way to keep order of my Belt.Map (Map.String), I use Map to simply map/get and merge another Map but I need to keep the initial order:

let first = Belt.Map.String.fromArray([("b", {"any": "value"}), ("a", {"any": "value"})])
Js.log(first->Belt.Map.String.toArray) // =>  [["a",{"any":"value"}],["b",{"any":"value"}]]

let second = Belt.Map.String.fromArray([("c", {"any": "value"}), ("b", {"any": "new value"})])

let all = Belt.Map.String.merge(first, second, (_key, a, b) => {
  switch b {
  | Some(b) => Some(b)
  | None =>
    switch a {
    | Some(a) => Some(a)
    | None => None
    }
  }
})

Js.log(all->Belt.Map.String.toArray) // => [["a",{"any":"value"}],["b",{"any":"new value"}],["c", 
{"any":"value"}]]

I need to have b,a,c

Is there a way to keep initial order or should I better use a simple array and merge by myself

Thanks

1 Like

You could use the native Map from JS? That preserves insertion order

1 Like

The Belt.Map structure uses an AVL tree internally which relies on sorting the keys. So it’s not possible for it to remember the insertion order.

One alternative is to use a list with Belt.List.getAssoc and Belt.List.setAssoc. These treat your list like a more basic kind of “map” which AFAIK will preserve insertion order. It’s probably similar to what you would do with using an array.

Note that the Belt maps use an AVL tree because it makes looking up items much more performant. Belt.Map.String.get will be more efficient than Belt.List.getAssoc. This is one of the tradeoffs you make when choosing a data structure.

If you need to preserve insertion order, then I assume you’re using your map with forEach or reduce to generate some other kind of value from it? In that case, a list (or an array) may be a better choice anyway.

1 Like

Thx for the explaination.
Belt.List work but I would have preferred an easiest way to merge two occurence.
setAssoc force me to do a forEach on my “second” list to add item one by one to the “first” one.

I guess you can indeed write bindings for JS ordered map if you prefer, I have some for https://github.com/marijnh/orderedmap if you’re interested:
https://github.com/wearegoat/bs-prosemirror/blob/master/src/orderedmap/OrderedMap.re

1 Like