通过与另一个对象部分匹配来查找对象

时间:2016-02-16 10:58:33

标签: javascript underscore.js immutable.js

我有以下数据:

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

id,uid和rci是三个不同的id属性(来自可怕的数据库合并)。

每个客户:

  • 至少拥有其中一项属性
  • 可能有三个身份

现在的问题是: 我必须使用与此类似的对象搜索此集合:

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

与集合中的第三个条目匹配,因为rci属性匹配。

显然,有这个解决方案:

let match;

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

但我正在寻找一个更优雅的解决方案。 我也在使用underscorejs。

注意:这是Immutable.js集合/地图/列表的POJO版本。如果使用Immutable.js可以实现同样的目标,那就太棒了:)

2 个答案:

答案 0 :(得分:1)

如果我正确地阅读了您的问题,搜索应该找到与undefined对象上的任何search键/值对匹配的内容(而非所有内容) )。

如果是这样,你可以通过弄清楚那些一次这些键是什么来提高效率,并在找到匹配后停止循环:

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

从ES2015(又名ES6)或Array#find的垫片开始,不需要任何下划线:

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

我们不需要您拥有的item[key] &&,因为我们会在开始搜索之前过滤掉undefined值的密钥,因此如果该项目没有密钥,item[key]不会是===的{​​{1}}匹配。

这是使用Babel REPL上的示例数据的ES2015版本的live example

答案 1 :(得分:0)

在普通的Javascript中,您可以使用Array#filter()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>');