【问题标题】:Find object by partial match with another object通过与另一个对象的部分匹配来查找对象
【发布时间】:2016-02-16 10:58:32
【问题描述】:

我有以下数据:

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

id、uid 和 rci 是三个不同的 id 属性(来自糟糕的数据库合并)。

每个客户:

  • 至少具有这些属性之一
  • 可能有所有三个 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
    }
  })
}) 

但我一直在寻找更优雅的解决方案。 我也在使用下划线。

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

【问题讨论】:

  • "if(item[key] && item[key] === search[key]) {" 您的搜索值都不能为零吗? (或任何其他虚假值?)
  • @T.J.Crowder 通常 ID 不能为零。但是,糟糕的数据库,谁知道...
  • 尚未检查它是否能满足您的要求,但 Underscore 有一个 IsMatch 功能:underscorejs.org/#isMatch
  • @Me.Name:不,因为他的示例 search 不会匹配第三个条目,因为第三个条目只有 rci 而不是 uidid。跨度>

标签: javascript underscore.js immutable.js


【解决方案1】:

如果我没看错你的问题,搜索应该会找到与 search 对象上的 anyundefined 键/值对匹配的内容(而不是全部)。

如果是这样,您可以通过找出这些键是一次并在找到匹配项后停止循环来提高效率:

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] 将不会是 @ 987654330@ 匹配 search[key]

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

【讨论】:

  • 只是一个关于 search[key] !== undefinedtypeof search[k] !== 'undefined' 的简短问题。在这种情况下什么更好?
  • @NinaScholz:我认为这在当今世界并不重要。 undefined 全局现在是只读的。 很久前,一个窗口中的undefined 不是另一个窗口中的=== undefined 存在问题。但是,仍然(遗憾的是)可以隐藏符号 undefined,因此,如果您正在编写一个可以在某个范围内执行的通用库,您将无法控制某人可能在哪里做了一些疯狂的事情,例如 var undefined = 42 ,您可能想对此进行辩护。 (续)
  • (continuing) 通常在这种情况下,无论如何你都有一个作用域函数(这样你就可以拥有特定于 lib 的私有全局变量),它提供了一种简单的方法来处理这种防御: (function(undefined) { ... })();我始终确保我可以信任undefined,所以我不必使用更长的typeof检查。
【解决方案2】:

在纯 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>');

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-12-29
    • 2021-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-13
    • 1970-01-01
    • 2013-05-07
    相关资源
    最近更新 更多