简体   繁体   中英

How to find differences between n arrays of objects

I have an array called props that contains n number of arrays with objects and all arrays contain the same number of objects.

Each object has 4 properties : participation_enabled , name , pathing_enabled , id and these properties can have different values in the other arrays for the same property id...

My goal is to find all object properties that are different in the other arrays of objects and store them in another array called diffs .

Let's take the following example:

[
  [
    {participation_enabled:"false", name:"PropEins", pathing_enabled:"true", id:"prop1"}, 
    {participation_enabled:"false", name:"User Status", pathing_enabled:"false", id:"prop2"}, 
    {participation_enabled:"false", name:"Initial ID", pathing_enabled:"false", id:"prop3"}, 
    {participation_enabled:"false", name:"User ID", pathing_enabled:"false", id:"prop4"}, 
    {participation_enabled:"false", name:"Subdomain", pathing_enabled:"false", id:"prop5"}
  ], 
  [
    {participation_enabled:"false", name:"PropEins", pathing_enabled:"false", id:"prop1"}, 
    {participation_enabled:"false", name:"Room", pathing_enabled:"false", id:"prop2"}, 
    {participation_enabled:"false", name:"Phase", pathing_enabled:"false", id:"prop3"}, 
    {participation_enabled:"false", name:"Custom Insight 4", pathing_enabled:"false", id:"prop4"}, 
    {participation_enabled:"false", name:"Subdomain", pathing_enabled:"false", id:"prop5"}
  ], 
  [
    {participation_enabled:"true", name:"PropEins", pathing_enabled:"true", id:"prop1"}, 
    {participation_enabled:"true", name:"User Status", pathing_enabled:"true", id:"prop2"}, 
    {participation_enabled:"true", name:"Trackingcode", pathing_enabled:"true", id:"prop3"}, 
    {participation_enabled:"false", name:"User ID", pathing_enabled:"false", id:"prop4"}, 
    {participation_enabled:"false", name:"Subdomain", pathing_enabled:"false", id:"prop5"}
  ]
]

For the above example the diffs array should contain the following objects:

[
  {id:"prop1", participation_enabled:["false","true"], pathing_enabled:["false","true"], index:0},
  {id:"prop2", participation_enabled:["false","true"], name:["User Status","Room"], participation_enabled:["false","true"], pathing_enabled:["false","true"], index:1},
  {id:"prop3", participation_enabled:["false","true"], name:["Initial ID","Phase","Trackingcode"], participation_enabled:["false","true"], pathing_enabled:["false","true"], index:2},
  {id:"prop4", name:["User ID","Custom Insight 4"], pathing_enabled:["false","true"], index:3}
]

Any advice greatly appreciated.

Not the most elegant way. But it works using underscore JS.

Hope this will helps you. Also add some error handling would be good idea.

EDIT Add support to use google underscore methods. Now all should work. https://sites.google.com/site/scriptsexamples/custom-methods/underscoregs#TOC-_values-Object-obj-

 var a = [ [ {participation_enabled:"false", name:"PropEins", pathing_enabled:"true", id:"prop1"}, {participation_enabled:"false", name:"User Status", pathing_enabled:"false", id:"prop2"}, {participation_enabled:"false", name:"Initial ID", pathing_enabled:"false", id:"prop3"}, {participation_enabled:"false", name:"User ID", pathing_enabled:"false", id:"prop4"}, {participation_enabled:"false", name:"Subdomain", pathing_enabled:"false", id:"prop5"} ], [ {participation_enabled:"false", name:"PropEins", pathing_enabled:"false", id:"prop1"}, {participation_enabled:"false", name:"Room", pathing_enabled:"false", id:"prop2"}, {participation_enabled:"false", name:"Phase", pathing_enabled:"false", id:"prop3"}, {participation_enabled:"false", name:"Custom Insight 4", pathing_enabled:"false", id:"prop4"}, {participation_enabled:"false", name:"Subdomain", pathing_enabled:"false", id:"prop5"} ], [ {participation_enabled:"true", name:"PropEins", pathing_enabled:"true", id:"prop1"}, {participation_enabled:"true", name:"User Status", pathing_enabled:"true", id:"prop2"}, {participation_enabled:"true", name:"Trackingcode", pathing_enabled:"true", id:"prop3"}, {participation_enabled:"false", name:"User ID", pathing_enabled:"false", id:"prop4"}, {participation_enabled:"false", name:"Subdomain", pathing_enabled:"false", id:"prop5"} ] ]; var diff = {}; a.forEach(function(val, i){ //first just init start object if (i == 0) { val.forEach(function(v1, ind){ diff[v1.id] = {}; diff[v1.id].index = [ind]; for (var key in v1) { diff[v1.id][key] = [v1[key]]; } }); } else { //for all other values add them into array and remove dups val.forEach(function(v1){ var id = v1.id; for (var key in v1) { diff[id][key].push(v1[key]); } }); } }); //now finalize data removing all that have only unique values for (var key in diff) { var nested = diff[key]; var index = nested.index.pop(); for (nestedKey in nested) { nested[nestedKey] = _.filter(nested[nestedKey], function(item, pos) { return nested[nestedKey].indexOf(item) == pos; }); if (nested[nestedKey].length < 2) {delete nested[nestedKey];} } diff[key].id = key; diff[key].index = index if (_.keys(diff[key]).length < 3) {delete diff[key];} } diff = _.values(diff); console.log(diff); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script> 

A pure js example. Note that if you can be sure all properties contain strings, you could replace the indexOf search with a object-property based approach to check for duplicates faster.

Important assumption:

  • An object's index in the array determines matching objects

 var sampleData = [ [ {participation_enabled:"false", name:"PropEins", pathing_enabled:"true", id:"prop1"}, {participation_enabled:"false", name:"User Status", pathing_enabled:"false", id:"prop2"}, {participation_enabled:"false", name:"Initial ID", pathing_enabled:"false", id:"prop3"}, {participation_enabled:"false", name:"User ID", pathing_enabled:"false", id:"prop4"}, {participation_enabled:"false", name:"Subdomain", pathing_enabled:"false", id:"prop5"} ], [ {participation_enabled:"false", name:"PropEins", pathing_enabled:"false", id:"prop1"}, {participation_enabled:"false", name:"Room", pathing_enabled:"false", id:"prop2"}, {participation_enabled:"false", name:"Phase", pathing_enabled:"false", id:"prop3"}, {participation_enabled:"false", name:"Custom Insight 4", pathing_enabled:"false", id:"prop4"}, {participation_enabled:"false", name:"Subdomain", pathing_enabled:"false", id:"prop5"} ], [ {participation_enabled:"true", name:"PropEins", pathing_enabled:"true", id:"prop1"}, {participation_enabled:"true", name:"User Status", pathing_enabled:"true", id:"prop2"}, {participation_enabled:"true", name:"Trackingcode", pathing_enabled:"true", id:"prop3"}, {participation_enabled:"false", name:"User ID", pathing_enabled:"false", id:"prop4"}, {participation_enabled:"false", name:"Subdomain", pathing_enabled:"false", id:"prop5"} ] ]; // Reduce an array of data arrays into one array of merged objects function dataReducer (matches, current) { current.forEach(function(obj, i) { if (!matches[i]) { matches[i] = obj; } else { matches[i] = mergeObj(matches[i], obj); } }); return matches; }; // Merge two matching objects function mergeObj(obj1, obj2) { Object.keys(obj1).forEach(function(key) { if (obj1[key] !== obj2[key]) { obj1[key] = [].concat(obj1[key]); if (obj1[key].indexOf(obj2[key]) == -1) { obj1[key].push(obj2[key]); } } }); return obj1; }; var result = sampleData.reduce(dataReducer, []); console.log(result); 

Check below code. May be this is not most optimal way but it solves the problem.

 var mainArray = [ [{ participation_enabled: "false", name: "PropEins", pathing_enabled: "true", id: "prop1" }, { participation_enabled: "false", name: "User Status", pathing_enabled: "false", id: "prop2" }, { participation_enabled: "false", name: "Initial ID", pathing_enabled: "false", id: "prop3" }, { participation_enabled: "false", name: "User ID", pathing_enabled: "false", id: "prop4" }, { participation_enabled: "false", name: "Subdomain", pathing_enabled: "false", id: "prop5" }], [{ participation_enabled: "false", name: "PropEins", pathing_enabled: "false", id: "prop1" }, { participation_enabled: "false", name: "Room", pathing_enabled: "false", id: "prop2" }, { participation_enabled: "false", name: "Phase", pathing_enabled: "false", id: "prop3" }, { participation_enabled: "false", name: "Custom Insight 4", pathing_enabled: "false", id: "prop4" }, { participation_enabled: "false", name: "Subdomain", pathing_enabled: "false", id: "prop5" }], [{ participation_enabled: "true", name: "PropEins", pathing_enabled: "true", id: "prop1" }, { participation_enabled: "true", name: "User Status", pathing_enabled: "true", id: "prop2" }, { participation_enabled: "true", name: "Trackingcode", pathing_enabled: "true", id: "prop3" }, { participation_enabled: "false", name: "User ID", pathing_enabled: "false", id: "prop4" }, { participation_enabled: "false", name: "Subdomain", pathing_enabled: "false", id: "prop5" }] ]; var resultArray = mainArray[0]; for (var i = 0; i < mainArray.length; i++) { var arrayTocheck = mainArray[i]; for (var outer = 0; outer < resultArray.length; outer++) { row = resultArray[outer]; if (i == 0) { row.participation_enabled = []; row.name = []; row.pathing_enabled = []; } for (var inner = 0; inner < resultArray.length; inner++) { var rowtoCheck = arrayTocheck[inner]; if (row.id == rowtoCheck.id) { if (!row.participation_enabled.includes(rowtoCheck.participation_enabled) && rowtoCheck.participation_enabled != "") { row.participation_enabled.push(rowtoCheck.participation_enabled); } if (!row.name.includes(rowtoCheck.name) && rowtoCheck.name != "") { row.name.push(rowtoCheck.name); } if (!row.pathing_enabled.includes(rowtoCheck.pathing_enabled) && rowtoCheck.pathing_enabled != "") { row.pathing_enabled.push(rowtoCheck.pathing_enabled); } break; } } resultArray[outer] = row; } } console.log(resultArray); 

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