使用纯JavaScript,给定一个对象集合和一个过滤对象,返回与过滤对象具有相同键/值对的集合中的对象。

3

我有一个使用 JavaScript 解决某个问题的伪代码,但我无法想象如何将其翻译成代码:

var sampleCollection = [
  { 'a': 1, 'b': 2, 'c': 3 },
  { 'a': 4, 'b': 5, 'c': 6 }
];

var sampleFilter = { 'a': 4, 'c': 6 };

function getCollectionFilter(collection,filter) {
    function collectionFilter(collection,filter) {
    //return if for each element in filter,
    //collection's key/value pair is same with filter's key/value pair
  }

  return collection.filter(collectionFilter);
}

getCollectionFilter(sampleCollection,sampleFilter);
// -> { 'a': 4, 'b': 5, 'c': 6};

我认为lodash有_.matches来解决这个问题,但我想知道为什么要以某种方式处理,并且如果采用其他方式会有什么影响和后果。
在现实世界中,为什么某些解决方案/做法是“最佳”的,会增加额外的奖励。

为什么该过滤器还会返回 'b': 5 - Aeolingamenfel
因为 ac 的值匹配,所以会出现这种情况吗? - AncientSwordRage
哦,好的,我误解了过滤器的工作方式。 - Aeolingamenfel
最简单的方法是:http://stackoverflow.com/a/38664372/747579 - Abdennour TOUMI
2个回答

3

使用 Array#filterArray#every 方法

var sampleCollection = [{
  'a': 1,
  'b': 2,
  'c': 3
}, {
  'a': 4,
  'b': 5,
  'c': 6
}];

var sampleFilter = {
  'a': 4,
  'c': 6
};

function getCollectionFilter(collection, filter) {
  // filter out elements and return
  return collection.filter(function(v) {
    // get all object keys 
    return Object.keys(filter)
      // use `every` method and check all values are equal
      .every(function(k) {
        // compare values
        return filter[k] == v[k];
      });
  })
}
console.log(
  getCollectionFilter(sampleCollection, sampleFilter)
);


使用ES6箭头函数可以将其变为一行代码。

var sampleCollection = [{
  'a': 1,
  'b': 2,
  'c': 3
}, {
  'a': 4,
  'b': 5,
  'c': 6
}];

var sampleFilter = {
  'a': 4,
  'c': 6
};

function getCollectionFilter(collection, filter) {
  return collection.filter(v => Object.keys(filter).every(k => filter[k] == v[k]))
}
console.log(
  getCollectionFilter(sampleCollection, sampleFilter)
);


0
类似于Pranav C Balan的回答(比我更快)...我只是使用一个过滤器工厂来创建函数,以便将其传递给Array.prototype.filter,而不是要求集合作为参数并在实际比较值之前进行预循环检查以查找匹配键的存在。
let filterer = test => {
  let keys = Object.keys(test).sort();
  let keyMatch = new RegExp(keys.toString);
  return obj => {
    let objKeys = Object.keys(obj).sort().toString();
    return objKeys.match(keyMatch) && keys.every(k => test[k] === obj[k]);
  }
};

let passes = arrOfObjects.filter(filterer(testCase));

感谢您提供额外的答案。Pranav的答案对我的代码进行了简洁的编辑使其能够正常运行。我注意到您正在使用ES6功能。与上面的代码相比,这在性能、可扩展性和可读性(样式采用)方面如何?我没有生产经验,因此我很好奇实际世界中的做法,而不是迄今为止接触到的孤立算法挑战。 - jpls93
@John 这取决于ES6是本地的还是转译的。根据我的经验,源代码通常会缩短25~30%。在实际应用中,我知道ES6/Babel或Typescript(使用与Babel相同的core-js转译器)是相当标准的。至于性能方面,我没有进行过分析,但除非它在热循环中,否则即使有数量级的差异也不应该有影响。 - Jared Smith

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接