Access objects by their identifier

304 views Asked by At

I'm fetching relational data from my sql database. This data has an identifier (unique/primary key). Sample:

[
   {id:1, value:“test“, cat:2},
   {id:2, value:“test“, cat:3},
   {id:3, value:“test“, cat:4}, ...
]

As proposed on many sites, including Stackoverflow, you may use an array's find function to access the elements by their id:

Find object by id in an array of JavaScript objects

Sample to fetch the value of object with id 3:

  SomeVal = myArray.find(x => x.id === 3).value

However, I disagree with this approach. I don't see why you would search for an identifier, as you could just simply access the element directly via id, which really is the idea to use an identifier.

You may argue that the array's find function will just do the job as it's superfast, but that's not good enough in my case as performance has highest priority.

As result, I currently "misuse" the index of the array as identifier number to access the elements directly. Sample:

 SomeVal = myArray[3].value

However, I am looking for a more feasable approach in javascript/typescript to access the elements by id directly.

I do not need to create/update/delete the elements, I solely need to access them once fetched.

I must not use arrays at all if another data structure is better for this.

I am NOT proposing to replace an array’s field search function such as find with the direct index access. And the core of the discussion shall not be which array element is accessed by 3, as this is a simple example. The main idea of the question is if it’s feasible to use the index if an array like it was the identifier, hence to use index which directly correlates with the id field.

3

There are 3 answers

2
T.J. Crowder On BEST ANSWER

However, I disagree with this approach. I don't see why you would search for an identifier, as you could just simply access the element directly via id, which really is the idea to use an identifier.

You can't directly access by ID with the structure you've shown. You need a different structure to do that.

As result, I currently "misuse" the index of the array as identifier number to access the elements directly. Sample:

SomeVal = myArray[3].value

That doesn't access the entry with id: 3. It accesses undefined (with your sample data). Indexes start at 0, not 1. Moreover, unless the underlying system guarantees it, you can't rely on the entries being in id order with no gaps, etc.

For access by id, convert the array to a Map or an object. Then you can reuse that map or object and benefit from the sublinear lookup time on the map key / object property name.

Map (I'd recommend this):

// Note that I've put them out of order to demonstrate we're really getting by id
const array = [
   {id:2, value:"test", cat:3},
   {id:1, value:"test", cat:2},
   {id:3, value:"test", cat:4},// ...
];

const map = new Map(array.map(entry => [entry.id, entry]));

console.log(map.get(1));

Object:

// Note that I've put them out of order to demonstrate we're really getting by id
const array = [
   {id:2, value:"test", cat:3},
   {id:1, value:"test", cat:2},
   {id:3, value:"test", cat:4},// ...
];

const obj = Object.fromEntries(array.map(entry => [entry.id, entry]));

console.log(obj[1]);

1
T. Short On

The reason you have to use find in this case is because you have an array of objects. So you cannot directly access the id key.

If you want to access the id key directly, then you need to convert your array to an object.

0
Ali Torki On

In my opinion, there are two approaches to do that.

  1. Using a data structure algorithm such as HashTable to find the element easily and in fast time.
  2. Create an object that id is key and its value is the entity object. something like this:
    const myArray = [...];
    const cachedMyArray = cacheData(myArray);
    
    const anItem = cachedMyArray[3]
    
    // Caching data to find elements fastest
    interface MyArray {
      ...
    }
    
    function cacheData(array: MyArray[]) {
      const cached = {};
      
      array.forEach((item: MyArray) => {
        cached[item.id] = item;
      });
      
      return cached;
    }