Stefan Stoychev
Stefan Stoychev

Reputation: 5012

Filter/Search JavaScript array of objects based on other array in Node JS

i have one array of ids and one JavaScript objects array. I need to filter/search the JavaScript objects array with the values in the array in Node JS.

For example

var id = [1,2,3];

var fullData = [ 
    {id:1, name: "test1"}
   ,{id:2, name: "test2"}
   ,{id:3, name: "test3"}
   ,{id:4, name: "test4"}
   ,{id:5, name: "test5"}
];

Using the above data, as a result i need to have :

var result = [ 
    {id:1, name: "test1"}
   ,{id:2, name: "test2"}
   ,{id:3, name: "test3"}
];

I know i can loop through both and check for matching ids. But is this the only way to do it or there is more simple and resource friendly solution.

The amount of data which will be compared is about 30-40k rows.

Upvotes: 0

Views: 207

Answers (2)

The Spooniest
The Spooniest

Reputation: 2873

As long as you're starting with an unsorted Array of all possible Objects, there's no way around iterating through it. @Cerbrus' answer is one good way of doing this, with Array.prototype.filter, but you could also use loops.

But do you really need to start with an unsorted Array of all possible Objects?

For example, is it possible to filter these objects out before they ever get into the Array? Maybe you could apply your test when you're first building the Array, so that objects which fail the test never even become part of it. That would be more resource-friendly, and if it makes sense for your particular app, then it might even be simpler.

function insertItemIfPass(theArray, theItem, theTest) {
    if (theTest(theItem)) {
        theArray.push(theItem);
    }
}

// Insert your items by using insertItemIfPass

var i;

for (i = 0; i < theArray.length; i += 1) {
    doSomething(theArray[i]);
}

Alternatively, could you use a data structure that keeps track of whether an object passes the test? The simplest way to do this, if you absolutely must use an Array, would be to also keep an index to it. When you add your objects to the Array, you apply the test: if an object passes, then its position in the Array gets put into the index. Then, when you need to get objects out of the Array, you can consult the index: that way, you don't waste time going through the Array when you don't need to touch most of the objects in the first place. If you have several different tests, then you could keep several different indexes, one for each test. This takes a little more memory, but it can save a lot of time.

function insertItem(theArray, theItem, theTest, theIndex) {
    theArray.push(theItem);
    if (theTest(theItem)) {
        theIndex.push(theArray.length - 1);
    }
}

// Insert your items using insertItem, which also builds the index

var i;

for (i = 0; i < theIndex.length; i += 1) {
    doSomething(theArray[theIndex[i]]);
}

Could you sort the Array so that the test can short-circuit? Imagine a setup where you've got your array set up so that everything which passes the test comes first. That way, as soon as you hit your first item that fails, you know that all of the remaining items will fail. Then you can stop your loop right away, since you know there aren't any more "good" items.

// Insert your items, keeping items which pass theTest before items which don't

var i = 0;

while (i < theArray.length) {
    if (!theTest(theArray[i])) {
        break;
    }
    doSomething(theArray[i]);
    i += 1;
}

The bottom line is that this isn't so much a language question as an algorithms question. It doesn't sound like your current data structure -an unsorted Array of all possible items- is well-suited for your particular problem. Depending on what else the application needs to do, it might make more sense to use another data structure entirely, or to augment the existing structure with indexes. Either way, if it's planned carefully, will save you some time.

Upvotes: 1

Cerbrus
Cerbrus

Reputation: 72927

This will do the trick, using Array.prototype.filter:

var result = fullData.filter(function(item){ // Filter fulldata on...
    return id.indexOf(item.id) !== -1; // Whether or not the current item's `id`
});                                    // is found in the `id` array.

Please note that this filter function is not available on IE 8 or lower, but the MDN has a polyfill available.

Upvotes: 2

Related Questions