1

Since the title is not easy to get, I'll provide an example :

var myObject = {
  "myArray": [{
"hashKey": "someHashkey1",
"data": "someData1"
  }, {
"hashKey": "someHashkey2",
"data": "someData2"
  }, {
"hashKey": "someHashkey3",
"data": "someData3"
  }]
};
        

I have "myObject" containing "myArray", and now I would like to efficiently find the index of the object having, for instance, the hashKey "someHashKey2".

I could build my own loop to check all elements in the array, but :

  1. is there a built-in way to do it ? Something like indexOf() ?

  2. is there a npm tool for that kind of need (I work in Node.js)

  3. is there an efficient way to work here ? some bad way to avoid ?

[EDIT :] My efficiency question is due to the fact that I will have to do this operation for basically all the hashKeys. I just found this question which has a "lookup" answer that could help. Still in the process of understanding it all...

Community
  • 1
  • 1
klonaway
  • 449
  • 3
  • 18

3 Answers3

1

You can simply use Array.prototype.findIndex to get index of every item you want.

var myObject = {"myArray": [{"hashKey": "someHashkey1", "data": "someData1"}, {"hashKey": "someHashkey2", "data": "someData2"}, {"hashKey": "someHashkey3", "data": "someData3"}] };

console.log(myObject.myArray.findIndex(i => i.hashKey === 'someHashkey2'));

If search call happens most of the time then you can use this hash to check or access your values:

Old Fashioned way

var myObject = {"myArray": [{"hashKey": "someHashkey1", "data": "someData1"}, {"hashKey": "someHashkey2", "data": "someData2"}, {"hashKey": "someHashkey3", "data": "someData3"}] };


hash = Object.create(null);
myObject.myArray.forEach(i => hash[i.hashKey] = i)

console.log('someHashkey2' in hash);
console.log(hash.someHashkey2);

New style

var myObject = {"myArray": [{"hashKey": "someHashkey1", "data": "someData1"}, {"hashKey": "someHashkey2", "data": "someData2"}, {"hashKey": "someHashkey3", "data": "someData3"}] };

var map = new Map;
myObject.myArray.forEach(i => map.set(i.hashKey, i));

console.log(map.has('someHashkey2'));
console.log(map.get('someHashkey2'));

Benefit of using map is that it allows you store anything as key and not just string

Morteza Tourani
  • 3,506
  • 5
  • 41
  • 48
  • @FelixKling I don't think that would be necessary. Isn't that description enought? – Morteza Tourani Jul 20 '16 at 18:59
  • @mortezaT – A plain code without explanation is never helpful...Care to explain what is happening... – Rayon Jul 20 '16 at 19:00
  • NOTE: findIndex is not supported in Internet Explorer as per the docs. – Tad Donaghe Jul 20 '16 at 19:01
  • 1
    @TadDonaghe – OP is under context of `node` so IMO, Browser Support should not be the concern... – Rayon Jul 20 '16 at 19:02
  • Thanks for this solution : I think this is the best answer to the question as I wrote it. However, I'm accepting a solution which makes use of my hash keys. Do you think it's a mistake to convert myArray into an object ? – klonaway Jul 20 '16 at 19:17
  • @KLôN If you want to use your values as object then there is no problem but if you just need it for finding the one you want I wont suggest that if searching happens few times. BTW You don't have that object now. – Morteza Tourani Jul 20 '16 at 19:26
  • @mortezaT : searching will happen many times. I'd say around half of the hashkeys will be searched by the end of the procedure... – klonaway Jul 20 '16 at 19:31
  • @mortezaT : thanks a lot for your efforts, I'm taking some time to understand how all of this works ! – klonaway Jul 20 '16 at 20:33
0

If you have an hash key I would recommend you to convert the array to an object and then you could find the object using the hash key like this: myObject.myArray["someHashkey1"]

var myObject = 
    { "myArray" : 
       {
         "someHashkey1":{
          "hashKey": "someHashkey1",
          "data": "someData1"
         },
         "someHashkey2":{
          "hashKey": "someHashkey2",
          "data": "someData2"
         }
       }
     };
     console.log(myObject.myArray["someHashkey1"]);

Here is a small performance test for array vs hash object as you can see there is a small difference between finding the same key in an array in an object. the object is a bit faster.

Shlomi Haver
  • 954
  • 9
  • 14
  • You're so right. With hash keys I'm better off that way. Only one question before accepting this answer : is there any loss in time efficiency when using your answer instead of an array-built structure ? (I'm not dealing with huge data, but I'm still wondering...) – klonaway Jul 20 '16 at 19:07
  • lovely, you are my hero (for an hour) ;-) – klonaway Jul 20 '16 at 20:31
0

Whenever you want to get one (non-boolean) value out of an array, you almost always want reduce:

var index = myObject.myArray.reduce((index, record, i) => {
  if (index !== -1 || !('somekey' in record)) {
    return index;
  } else {
    return i;
  }
}, -1);

Or 'golfed':

var index = myObject.myArray.reduce((i, x, j) => {i || x.somekey ? i : j},-1);
Jared Smith
  • 19,721
  • 5
  • 45
  • 83
  • reduce is not a good choice, because you need to iterate until the end, even if ther is a find in the middle or at the beginning. better use some. – Nina Scholz Jul 20 '16 at 19:30
  • @NinaScholz but some only gets you a boolean, not an index. And unless the data set is exceedingly large, or the function is called quite often on different data sets, I fail to see how the microseconds difference between this and a `for` loop with a `break` matters in the slightest, whereas this is a pretty clear win in terms of testability and compactness. – Jared Smith Jul 21 '16 at 14:20