Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find object by partial match with another object

I have the following data:

 let Collection = [{
    id: '1',
    uid: 'u1',
    rci: 'r1',
    name: 'ClientName'
  }, {
    uid: 'u2',
    name: 'ClientName 2'
  }, {
    rci: 'r3',
    name: 'ClientName 3'
  }]

id, uid and rci are three different id properties (result from terrible database merge).

Every client:

  • Has at least one of these properties
  • May have all three id

Now the question: I have to search this collection with an object that looks similar to this:

search: {
    id: undefined,
    uid: 'u3',
    rci: 'r3'
}

which matches the third entry in the collection, because the rci properties match.

Obviously, there's this solution:

let match;

let test = Collection.forEach(item => {
  Object.keys(search).forEach(key => {
    console.log('iteration')
    if(item[key] && item[key] === search[key]) {
        match = item
    }
  })
}) 

But I was looking for a little more elegant solution. I'm also using underscorejs.

NOTE: This are POJO versions of Immutable.js collections/maps/lists. If the same thing is achievable with Immutable.js it would be great :)

like image 851
Ivan Pidov Avatar asked Jul 15 '26 05:07

Ivan Pidov


2 Answers

If I'm reading your question right, the search should find something that matches any non-undefined key/value pair on the search object (rather than all).

If so, you can make that a bit more efficient by figuring out what those keys are once, and stopping looping once you find a match:

let keys = Object.keys(search).filter(key => search[key] !== undefined);
let match = _.find(Collection, item => keys.some(key => item[key] === search[key]));

As of ES2015 (aka ES6), or with a shim for Array#find, no Underscore would be needed:

let keys = Object.keys(search).filter(key => search[key] !== undefined);
let match = Collection.find(item => keys.some(key => item[key] === search[key]));

We don't need the item[key] && you had because we filter out keys with undefined values before we start the search, so if the item doesn't have a key, item[key] won't be a === match for search[key].

Here's a live example of the ES2015 version using your sample data on Babel's REPL.

like image 125
T.J. Crowder Avatar answered Jul 18 '26 04:07

T.J. Crowder


In plain Javascript you can use Array#filter() and Array#some().

function find(array, search) {
    var s = {};
    Object.keys(search).forEach(function (k) {
        if (typeof search[k] !== 'undefined') {
            s[k] = search[k];
        }
    });
    return array.filter(function (a) {
        return Object.keys(s).some(function (k) {
            return s[k] === a[k];
        });
    });
}

var collection = [{ id: '1', uid: 'u1', rci: 'r1', name: 'ClientName' }, { uid: 'u2', name: 'ClientName 2' }, { rci: 'r3', name: 'ClientName 3' }],
    result = find(collection, { id: undefined, uid: 'u3', rci: 'r3' });

document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
like image 22
Nina Scholz Avatar answered Jul 18 '26 05:07

Nina Scholz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!