1

I've run across a codewars exercise which I'm struggling with: https://www.codewars.com/kata/scraping-codewars-top-500-users/train/javascript

I want to be able to access an array as if was 1-indexed, instead of 0-indexed.

For example, if I have this array:

let a = [1, 2, 3, 4, 5]

I would like to do a[5] and get 5 as a result (instead of 4).

So far, I've come up with this:

Array.prototype.get = function(i, fallback) {
  return this[i-1] || fallback;
}

And with:

class BaseOneArray extends Array {
    constructor(...args) { 
        super(...args); 
    }
    get(i, fallback) {
        return this[i-1];
    }
}

However, both of these approaches only work when accessing the array like this: a.get(4) but not when doing it like this: a[4]

How could I make the [] operators from an array work as if the array had a 1-based index?

The array must have the same number of items, so I can't just add a fill value in the first position to move all the elements one place up.

Xar
  • 7,572
  • 19
  • 56
  • 80
  • Potentially relevant: https://stackoverflow.com/questions/1711357/how-would-you-overload-the-operator-in-javascript – OliverRadini Aug 10 '18 at 12:24

3 Answers3

2

To influence property accesses you could use a proxy that increases every property access:

  array =  new Proxy(array, {
    get(target, prop, receiver) {
      if(!isNaN(+prop)) --prop;
      return Reflect.get(target, prop, receiver);
    },
    set(target, prop, value) {
      if(!isNaN(+prop)) --prop;
      return Reflect.set(target, prop, value);
    },
  });

By proxying the underlying array still stays zero based, just your "view" of it is changed so if the array is used somewhere else that doesnt get affected.

Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
1

If you can modify the array then you can do something like this.

let a = [1, 2, 3, 4, 5]
a = [undefined, ...a];

console.log("a[5] is ", a[5]);
console.log("a[0] is ", a[0]); // Same as accessing any undefined index. See below
console.log("a[100] is ", a[100]);
void
  • 36,090
  • 8
  • 62
  • 107
1

The code test does not specify you need an array, it just says "Leaderboard#position[i] should return the ith ranked User(1 based index)". You should be able to simply use an object with numeric keys then:

const leaderboard = yourFetchedAndParsedLeaderboardDomElementArray
  .reduce((acc, row, index) => Object.assign(acc, {
    [index + 1]: {
      // get the following ones from `row` somehow:
      name: ...,
      clan: ...,
      author: ...
    }
  }), {});

You can use the object spreading syntax if available rather than Object.assign.

sp00m
  • 47,968
  • 31
  • 142
  • 252