简体   繁体   中英

How to compare two array of object and get common objects

Hello guys I have two arrays

var elements = [{
        "id": "id_1",
        "type": "input",
        "businesstype": { "type": "text" }
    },
    {
        "type": "label",
        "id": "id_234"
    },
    {
        "id": "id_16677",
        "type": "div",
    },
    {
        "id": "id_155",
        "type": "input",
        "businesstype": { "type": "password" }
    }
]

var filterArray=[{type:'input',businesstype:{type:'text'}},{type:'div'}]

and want common obejct like

var output = [{
        "id": "id_1",
        "type": "input",
        "businesstype": { "type": "text" }
    },
    {
        "id": "id_16677",
        "type": "div",
    }
]

How do I compare these two objects to get equal objects from elements.

You could filter it with a recursive approach for the nested objects.

 const isObject = o => o && typeof o === 'object', isEqual = (f, o) => isObject(o) && Object.keys(f).every(k => isObject(f[k]) && isEqual(f[k], o[k]) || o[k] === f[k] ); var elements = [{ id: "id_1", type: "input", businesstype: { type: "text" } }, { type: "label", id: "id_234" }, { id: "id_16677", type: "div" }, { id: "id_155", type: "input", businesstype: { type: "password" } }], filterArray = [{ type: 'input', businesstype: { type: 'text' } }, { type: 'div' }], result = elements.filter(o => filterArray.some(f => isEqual(f, o))); console.log(result); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

If your filterArray does not have further objects in its hierarchy, you can make do with this solution - see demo below:

 var elements=[{id:"id_1",type:"input",businesstype:{type:"text"}},{type:"label",id:"id_234"},{id:"id_16677",type:"div"},{id:"id_155",type:"input",businesstype:{type:"password"}}],filterArray=[{type:"input",businesstype:{type:"text"}},{type:"div"}]; var result = elements.filter(function(e) { return filterArray.some(function(f) { return Object.keys(f).every(function(k) { return e.hasOwnProperty(k) && Object.keys(f[k]).every(function(n) { return e[k][n] == f[k][n]; }); }); }); }); console.log(result); 
 .as-console-wrapper {top: 0;max-height: 100%!important;} 

(Since you tagged Ramda)

Ramda already has many useful (object) comparison functions you can use to make the filter a bit easier to read. (ie: equals and other functions that use it under the hood, like contains )

You could, for example, write:

const elements=[{id:"id_1",type:"input",businesstype:{type:"text"}},{type:"label",id:"id_234"},{id:"id_16677",type:"div"},{id:"id_155",type:"input",businesstype:{type:"password"}}];
const filterArray=[{type:'input',businesstype:{type:'text'}},{type:'div'}];

// Describes how to define "equality"
// i.e.: elements are equal if type and businesstype match
// e.g.: pick(["a", "b"], { a: 1, b: 2, c: 3}) -> { a: 1, b: 2}
const comparisonObjectFor = pick(["type", "businesstype"]);

// Compares an object's comparison representation to another object
const elEquals = compose(whereEq, comparisonObjectFor);

// Creates a filter method that searches an array
const inFilterArray = matchElements => el => any(elEquals(el), matchElements);

// Run the code on our data
filter(inFilterArray(filterArray), elements);

Running example here

I don't think this is necessarily the best solution (in terms of reusability, readability), but I'd advice you to not inline deep object/array comparison methods since:

  1. You're probably going to use them more than once
  2. They are hard to understand/predict if not given the right name & documentation
  3. They are prone to (small) bugs because of their complexity

In other words: since you've tagged lodash and Ramda, I can safely advice to use a well tested, well used library for the comparison of your objects .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM