2

At present I've been using nested for loops to solve this issue:

for (var i = 0; i < this.props.trackedPlayers.length; i++)
{
    for (var j = 0; j < PHP_VARS.players_data.length; j++)
    {
        // This check here is the key part
        if (PHP_VARS.players_data[j]._id == this.props.trackedPlayers[i]._id)
        {
            data.push(// stuff from both arrays..);
        }
    }
}

However I figured there might be a boilerplate function that does this already. Done a few searches but nothing cropped up - any pointers, or is this the best I've got for now?

EDIT: Brief explanation, trackedPlayers are all from players_data. By checking if each player in the (generally) larger players_data is in trackedPlayers, I know whether or not to list them as an option for 'adding' to an HTML select field.

Dezachu
  • 153
  • 1
  • 2
  • 10
  • You should clarify what "stuff from both arrays" is. Does it need the `i` and `j` indices? Only the common `_id`? Are `_id` strings? Can there be repetitions? – Oriol May 08 '16 at 19:07
  • Also see [Simplest code for array intersection in javascript](http://stackoverflow.com/q/1885557/1529630) – Oriol May 08 '16 at 19:11
  • @Dezachu, it would be better if you added `this.props.trackedPlayers` and `PHP_VARS.players_data` contents – RomanPerekhrest May 08 '16 at 19:17
  • @Oriol 'stuff from both arrays' is a bunch of generic malarkey that isn't relevant to the question. The important part (to me, at least) is that I'm having to iterate through the entirety of the second array for each element in the first. It's a relatively weighty implementation (larger the arrays get, the heavier) so was simply seeking a better way. The contents of the structures do not matter beyond knowing that trackedPlayers are identical to X fields from players_data – Dezachu May 08 '16 at 21:52

2 Answers2

1

You could use an object as hash table and iterate over both arrays, first for the building of the hash table and the second for test and further operations.

var object = Object.create(null);
this.props.trackedPlayers.forEach(function (a) {
    object[a._id] = a;
});
PHP_VARS.players_data.forEach(function (a) {
    if (object[a._id]) {
        // access data from this.props.trackedPlayers
        // with object[a._id]._id as example
        // access data from  PHP_VARS.players_data
        // with a._id as example
        data.push(/* stuff from both arrays..*/);
    }
});
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • How do you know that "stuff from both arrays" doesn't need `i` and `j` indices? The question is not clear. – Oriol May 08 '16 at 19:09
  • the reference from the first is in `object`, and the second is the actual element `a`. – Nina Scholz May 08 '16 at 19:14
  • @NinaScholz I don't know about the downvote but it might be a good idea to explicit say that the object from `trackedPlayers` can be found on `object[a._id]` while the object from `players_data` can be found under `a` – Andreas Louv May 08 '16 at 19:17
  • 1
    I didn't downvote. I would have answered something like this if the question was more clear. – Oriol May 08 '16 at 19:33
  • 1
    @Gothdo, what do you mean with *The code in question looks simpler to me*? in case of complexity, this solution provides O(n+m) instead of the op's complexity of O(n*m). – Nina Scholz May 08 '16 at 19:48
0

lodash library has _.intersectionBy() function which does exactly what you want. Using this, you could change your code to that:

_.intersectionBy([PHP_VARS.players_data, this.props.trackedPlayers], "_id")
  .forEach(element=> {
    data.push(/* ... */)
  })

or, using for...of loop:

const intersection = _.intersectionBy([PHP_VARS.players_data, this.props.trackedPlayers], "_id")
for (element of intersection) {
  data.push(/* ... */)
}
Michał Perłakowski
  • 88,409
  • 26
  • 156
  • 177