简体   繁体   English

比较对象数组。 返回匹配的对象键和值

[英]Compare Object Arrays. Return matching Object keys & values

OBJECTIVE 目的

Make a function that looks through a list (collection) and returns an array of all objects that have equivalent property values (source). 创建一个通过列表(集合)查找并返回具有相等属性值的所有对象(源)的数组的函数。


EXAMPLE #1 示例#1

    function where(collection, source) {
      var arr = [];
      return arr;
    }

    where([
        { first: 'Romeo', last: 'Montague' }, 
        { first: 'Mercutio', last: null }, 
        { first: 'Tybalt', last: 'Capulet' }], 

        { last: 'Capulet' });

EXPECTED OUTPUT #1 预期输出#1

[{ first: 'Tybalt', last: 'Capulet' }]

EXAMPLE #2 例子#2

where(
    [{ 'a': 1 }, 
     { 'a': 1 },  
     { 'a': 1, 'b': 2 }], 

     { 'a': 1 }), 

EXPECTED OUTPUT #2 预期输出#2

[{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }]

QUESTIONS 质询

  1. Typically I include some Psuedo-code to highlight my thought process. 通常,我会包含一些伪代码来突出我的思考过程。 However, I think I've fallen too deep into the rabbit hole. 但是,我认为我已经掉进了兔子洞的深处。 What is the best approach here? 最好的方法是什么? Should I flatten the objects into arrays? 我应该将对象展平为数组吗? Is there an equivalent indexOf() for objects? 对象是否具有等效的indexOf()?
  2. I've heard you can use Object.keys() and .hasOwnProperty() to help accomplish this, but cannot comprehend how these two methods would work together to tackle this problem. 我听说您可以使用Object.keys()和.hasOwnProperty()来帮助完成此任务,但无法理解这两种方法如何共同解决该问题。

Since you can't use external libraries, here's a simple way to do what you need: 由于您不能使用外部库,因此这是一种执行所需操作的简单方法:

function where(collection, source) {
   var keys = Object.keys(source);

   return collection.filter(function (item) {
      return keys.every(function (key) {
         return source[key] == item[key];
      });
   });
}

-> Solution 1: Using Lodash Where ->解决方案1: Where Lodash Where使用Where

For this kind of problems, you can use Lodash utility library. 对于此类问题,可以使用Lodash实用程序库。

Lodash already has where function which you need. Lodash已经具有您需要的where功能。

see the below example. 请参阅以下示例。

 var out = _.where([{ first: 'Romeo', last: 'Montague' }, { first: 'Mercutio', last: null }, { first: 'Tybalt', last: 'Capulet' }], { last: 'Capulet' }); document.getElementById('out').innerHTML = JSON.stringify(out); var out2 = _.where( [{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }], { 'a': 1 }); document.getElementById('out2').innerHTML = JSON.stringify(out2); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.8.0/lodash.js"></script> <div id="out"></div> <hr/> <div id="out2"></div> 


-> Solution 2: Custom Where Implementation - >解决方案2:自定义Where执行

This implementation works with strings, single object , one level object and multilevel objects . 此实现适用于字符串,单个对象,一个一级对象和多个一级对象

function typeOf(o) {
  return Object.prototype.toString.call(o).split(' ')[1].split(']')[0].toLowerCase();
}

function isUndefined(o) {
  return typeOf(o) === 'undefined';
}

function where(collection, source) {
  var checkArr = [];

  if (typeOf(collection) === 'object') {
    checkArr = [collection];
  } else if (typeOf(collection) === 'array') {
    checkArr = collection;
  }

  function isObjectSemiSame(obj, source, u) {
    return Object.keys(source).every(function(key) {
      if (isUndefined(obj) || isUndefined(obj[key])) {
        return;
      }
      if (typeOf(source[key]) === 'object' || typeOf(source[key]) === 'array') {
        return isObjectSemiSame(obj[key], source[key]);
      }
      return source[key] === obj[key];
    });
  }

  return checkArr.filter(function(item) {
    return isObjectSemiSame(item, source);
  });
}

Jasmine tests for testing where with strings, single object, one level object and multilevel objects. 茉莉测试用于测试where用字符串,单个对象,一个级别对象和多级的对象。

 function typeOf(o) { return Object.prototype.toString.call(o).split(' ')[1].split(']')[0].toLowerCase(); } function isUndefined(o) { return typeOf(o) === 'undefined'; } function where(collection, source) { var checkArr = []; if (typeOf(collection) === 'object') { checkArr = [collection]; } else if (typeOf(collection) === 'array') { checkArr = collection; } function isObjectSemiSame(obj, source, u) { return Object.keys(source).every(function(key) { if (isUndefined(obj) || isUndefined(obj[key])) { return; } if (typeOf(source[key]) === 'object' || typeOf(source[key]) === 'array') { return isObjectSemiSame(obj[key], source[key]); } return source[key] === obj[key]; }); } return checkArr.filter(function(item) { return isObjectSemiSame(item, source); }); } describe('where method', function() { it('testing with strings', function() { var collection = [ "one", "two", "three" ]; var collection = [ "bamboo", "two", "bamboo", "link" ]; expect(where(collection, "two")).toEqual(["two"]); expect(where(collection, "bamboo")).toEqual(["bamboo", "bamboo"]); }); it('testing with one object', function() { var collection1 = { name: 'raju', age: 23, }; var collection2 = { name: 'Friko', age: 36, }; expect(where(collection1, { name: 'raju' })).toEqual([collection1]); expect(where(collection1, { name: 'Dump' })).toEqual([]); expect(where(collection2, { age: 36 })).toEqual([collection2]); expect(where(collection2, { car: 'audi' })).toEqual([]); }); it('testing with one level object', function() { var collection = [{ name: 'jack', age: 25 }, { name: 'missi', age: 23 }, { name: 'reddy', age: 46 }]; var source1 = { name: 'reddy' }; var source2 = { age: 25 }; expect(where(collection, source1)).toEqual([collection[2]]); expect(where(collection, source2)).toEqual([collection[0]]); }); it('testing with multilevel object', function() { var collection = [{ name: 'jack', age: 25, level1: { name: 'l1', level2: { name: 'l2', level3: { name: 'l3' } } } }, { name: 'missi', age: 23, level1: { name: 'l1' } }, { name: 'reddy', age: 46, feature: { flag: false } }]; var source1 = { level1: { name: 'l1' } }; var source2 = { level1: { name: 'l1', level2: { name: 'l2' } } }; var source3 = { feature: { flag: false } }; expect(where(collection, source1).length).toBe(2); expect(where(collection, source1)).toEqual(jasmine.arrayContaining([ collection[0], collection[1] ])); expect(where(collection, source2)).toEqual([collection[0]]); expect(where(collection, source3)).toEqual([collection[2]]); }); }); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.2.1/jasmine.min.js"></script> <link href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.2.1/jasmine.min.css" rel="stylesheet" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.2.1/jasmine-html.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.2.1/boot.min.js"></script> 

UPDATE: added custom where implementation with jasmine tests 更新:添加了使用茉莉花测试实现的自定义where

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Javascript - 比较两个数组。 如果在两者中都找到了对象,请更改它 - Javascript - Compare two arrays. If object is found in both, change it 通过将对象键与值匹配来映射两个单独的数组 - Map two separate arrays by matching object keys to values 按键分组的对象数组的总和值并返回到新的数组数组中 - Sum values of array of object grouped by keys and return into a new array of arrays Zip 数组作为对象的键和值 - Zip arrays as keys and values of an Object 通过 javascript 键比较两个 object arrays - compare two object arrays by javascript keys 希望比较两个 arrays - 如果两个键匹配,则返回 object 在 React 中都匹配 - Looking to compare two arrays - if the two keys match then return the object where both match in React 比较对象属性键与数组中的对象属性值,返回“总点数” - Compare Object Property Keys with Object Property Values in Array, Return “Total Points” Object.keys() 和 Object.values() 方法是否返回保留相同顺序的数组 - Do Object.keys() and Object.values() methods return arrays that preserve the same order 将 2 个 arrays 转换为键值 object,一个数组保存键,第二个是匹配索引值的嵌套数组 - convert 2 arrays into key value object, one array hold the keys, they second is nested array of matching indexed values 根据匹配键添加对象值 - Adding object values based on matching keys
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM