# Method to access the \`nth\` inserted element in a map

**URL:** <https://es.discourse.group/t/method-to-access-the-nth-inserted-element-in-a-map/1925>\
**Category:** 💡 Ideas\
**Tags:** proposal\
**Created:** [February 15, 2024, 6:37am UTC](https://es.discourse.group/t/method-to-access-the-nth-inserted-element-in-a-map/1925 "2024-02-15T06:37:45Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![christianscott](https://avatars.discourse-cdn.com/v4/letter/c/ecc23a/32.png) [@christianscott](https://es.discourse.group/u/christianscott)\
**Post date:** [February 15, 2024, 6:37am UTC](https://es.discourse.group/t/method-to-access-the-nth-inserted-element-in-a-map/1925/1 "2024-02-15T06:37:45Z")

</div>

For example:

```ts
const map = new Map();
map.set(1, 2);
map.set(3, 4);
console.log(map.nth(1)); // [3, 4]

```

Preserved insertion order is a handy feature of Maps. It makes them more useful for building caches with eviction policies. For example, you can build an LRU cache by deleting and re-inserting items when they are accessed.

While implementing the SIEVE algorithm in JS, I noticed that an `.nth()` method would be handy. Without it, I need to track insertion order in a seperate array, OR copy the keys into an array (`[...map.keys()][i]`).

This is how simple it would be w/ an .nth method (I think this is wrong but pls ignore 🙇‍♂️)

```ts
  evict() {
    let hand = this.hand;
    if (hand == null) {
      hand = this.items.size - 1;
    }
    while (this.items.nth(hand).visited) {
      this.items.nth(hand).visited = false;
      hand--;
      if (hand < 0) {
        hand = this.items.size - 1;
      }
    }
    this.items.delete(this.items.nth(hand).key);
    this.hand = hand - 1;
  }

```

This would use less memory than is currently possible (AFAICT).

Unsure of the feasibility of this feature as I do not understand how insertion order is typically tracked today.

Apologies for sloppy writing, writing this quickly before leaving the office :)

---

<div class="post-metadata">

**Author:** ![bergus](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/bergus/32/152_2.png) [@bergus](https://es.discourse.group/u/bergus)\
**Post date:** [February 15, 2024, 11:20am UTC](https://es.discourse.group/t/method-to-access-the-nth-inserted-element-in-a-map/1925/2 "2024-02-15T11:20:27Z")

</div>

The purpose of preserving insertion order is to enable deterministic operation across implementations, not to provide fast indexed access.

With the [_iterator helpers_ proposal](https://github.com/tc39/proposal-iterator-helpers) you can write `.nth(hand)` as `.keys().drop(hand).next().value`. It's a bit verbose, but explicit on what's actually happening.  
(See also the discussions on `.at()` at [Array.prototype.at compatibility? · Issue #148 · tc39/proposal-iterator-helpers · GitHub](https://github.com/tc39/proposal-iterator-helpers/issues/148) and [This seems to be missing `at()`? · Issue #279 · tc39/proposal-iterator-helpers · GitHub](https://github.com/tc39/proposal-iterator-helpers/issues/279))

---

<div class="post-metadata">

**Author:** ![bakkot](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/bakkot/32/22_2.png) [@bakkot](https://es.discourse.group/u/bakkot)\
**Post date:** [February 17, 2024, 8:23pm UTC](https://es.discourse.group/t/method-to-access-the-nth-inserted-element-in-a-map/1925/3 "2024-02-17T20:23:18Z")

</div>

> [@christianscott](#):
>
> Unsure of the feasibility of this feature as I do not understand how insertion order is typically tracked today.

Different implementations use different strategies, but I don't think any of them afford efficient indexing. (Firefox and Chrome use [something like this](https://wiki.mozilla.org/User:Jorend/Deterministic_hash_tables), while Safari [uses a linked list](https://github.com/tc39/proposal-set-methods/issues/91).)

And if getting the `n`th item takes linear time, it's not worth providing a method for it - for example, your code snippet would take quadratic time, which is bad.

---

<div class="post-metadata">

**Author:** ![aclaymore](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/aclaymore/32/501_2.png) [@aclaymore](https://es.discourse.group/u/aclaymore)\
**Post date:** [February 17, 2024, 10:35pm UTC](https://es.discourse.group/t/method-to-access-the-nth-inserted-element-in-a-map/1925/4 "2024-02-17T22:35:07Z")

</div>

Yeah, my understanding of those implementations is that while there is an ordered list, there are also tombstones so can't directly index.

---

<div class="post-metadata">

**Author:** ![claudiameadows](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/claudiameadows/32/126_2.png) [@claudiameadows](https://es.discourse.group/u/claudiameadows)\
**Post date:** [March 7, 2024, 4:05pm UTC](https://es.discourse.group/t/method-to-access-the-nth-inserted-element-in-a-map/1925/5 "2024-03-07T16:05:13Z")

</div>

Will note that such an "at" method, while not constant-time, would still see a perf boost as it doesn't require actually reading intermediate values, only what's minimally necessary to know if a tombstone is reached. For large maps, this could easily use SIMD.

However, I'm struggling to see other use cases here.
