admin管理员组

文章数量:1293755

I have a need to calculate percentages of match between 2 Javascript objects. How can I achieve this?

Examples:

obj1={key1: "val1", key2: "val2", key3: "val3", key4: "val4"}
obj2={key5: "val5", key6: "val6"}
//result should be: 0%


obj1={key1: "val1", key2: "val2", key3: "val3", key4: "val4"}
obj2={key1: "val1", key2: "val2"}
//result should be: 50%

I have a need to calculate percentages of match between 2 Javascript objects. How can I achieve this?

Examples:

obj1={key1: "val1", key2: "val2", key3: "val3", key4: "val4"}
obj2={key5: "val5", key6: "val6"}
//result should be: 0%


obj1={key1: "val1", key2: "val2", key3: "val3", key4: "val4"}
obj2={key1: "val1", key2: "val2"}
//result should be: 50%
Share asked Feb 10, 2017 at 15:43 Dhekra ZELAITIDhekra ZELAITI 1041 silver badge10 bronze badges 2
  • 2 % of matched keys or values? – ibrahim mahrir Commented Feb 10, 2017 at 15:44
  • 2 What have you tried? Where did it go wrong? People are willing to help, not do it for you. – jdmdevdotnet Commented Feb 10, 2017 at 15:44
Add a ment  | 

3 Answers 3

Reset to default 6

You have not specified exactly how you want such a percentage calculated. There are at least four different ways of measuring percent similarity between two objects:

  • the percent of the keys in the 1st object that can be found in the 2nd,
  • the percent of the values in the 1st object that can be found in the 2nd, including duplicates,
  • the percent of the values in the 1st object that can be found in the 2nd, with no duplicates allowed, and
  • the percent of {key:value} pairs in the 1st object that can be found in the 2nd object.

Note that order of the two objects matters, i.e. calling with (obj1,obj2) may produce different results than calling with (obj2,obj1).

The second option above counts each instance of repeated values in the 2nd object, making it possible to return values higher than 100%, e.g. paring {a:42} and {x:42, y:42} returns 200%. This might not initially seem reasonable but is mathematically valid based on how the calculation is defined. Such duplicates are not allowed in the third option, such that paring {a:42} and {x:42, y:42} returns 100%. In either case, duplicate values in the first object are not counted, e.g. paring {a:42, b:42} and {x:42} yields 50% in both cases. Such duplicates are not a relevant consideration for the first and fourth options above as JavaScript objects cannot have repeated keys.

The code snippet below demonstrates all four methods.

const obj1 = {a: 1, b: 2, c: 3, d: 3};
const obj2 = {a: 1, b: 1, e: 2, f: 2, g: 3, h: 5};

const keys = obj => Object.keys(obj);
const toPct = a => 100 / keys(a).length;

const pctSameKeys = (a, b) =>
  keys(b).reduce((num,key) =>
    keys(a).indexOf(key) > -1 ? num + 1 : num, 0) * toPct(a);

const pctSameValuesIncludingDuplicates = (a, b) =>
  keys(b).map(key => b[key]).reduce((num,v) =>
    keys(a).map(key => a[key]).indexOf(v) > -1 ? num + 1 : num, 0) * toPct(a);

const pctSameValuesNoDuplicates = (a, b) =>
  Array.from(new Set(keys(b).map(key => b[key]))).reduce((num,v) =>
    keys(a).map(key => a[key]).indexOf(v) > -1 ? num + 1 : num, 0) * toPct(a);

const pctSameProps = (a, b) =>
  keys(b).reduce((num,key) =>
    a[key] === b[key] ? num + 1 : num, 0) * toPct(a);

console.log('obj1:', JSON.stringify(obj1));
console.log('obj2:', JSON.stringify(obj2));
console.log('% same keys:                   ', pctSameKeys(obj1, obj2));
console.log('% same values, incl duplicates:', pctSameValuesIncludingDuplicates(obj1, obj2));
console.log('% same values, no duplicates:  ', pctSameValuesNoDuplicates(obj1, obj2));
console.log('% same properties (k/v pairs): ', pctSameProps     (obj1, obj2));

The following code snippet shows essentially exactly the same thing, but is written in an even more functional style (but see this answer on the Computer Engineering site to see how my code here can potentially be re-written in a still functional but more readable style):

const obj1 = {a: 1, b: 2, c: 3, d: 3};
const obj2 = {a: 1, b: 1, e: 2, f: 2, g: 3, h: 5};

// x or X is key or value or key/value pair

const getXs = (obj, getX) =>
  Object.keys(obj).map(key => getX(obj, key));

const getPctSameXs = (getX, filter) =>
  (objA, objB) =>
    (filter ? filter(getXs(objB, getX)) : getXs(objB, getX)).reduce(
      (numSame, x) =>
        getXs(objA, getX).indexOf(x) > -1 ? numSame + 1 : numSame,
      0
    ) / Object.keys(objA).length * 100;

const pctSameKeys       = getPctSameXs((obj, key) => key);
const pctSameValsDups   = getPctSameXs((obj, key) => obj[key]);
const pctSameValsNoDups = getPctSameXs((obj, key) => obj[key], vals => [...new Set(vals)]);
const pctSameProps      = getPctSameXs((obj, key) => JSON.stringify( {[key]: obj[key]} ));

console.log('obj1:', JSON.stringify(obj1));
console.log('obj2:', JSON.stringify(obj2));
console.log('% same keys:                   ', pctSameKeys      (obj1, obj2));
console.log('% same values, incl duplicates:', pctSameValsDups  (obj1, obj2));
console.log('% same values, no duplicates:  ', pctSameValsNoDups(obj1, obj2));
console.log('% same properties (k/v pairs): ', pctSameProps     (obj1, obj2));

It's not pletely clear from your limited number of examples exactly how it should behave, but I believe your requirement can be re-worded:

What percentage of items in obj1 exist and are equal in obj2?

For this, you can simply count:

var count = [0,0];
for( var key in obj1) {
    count[1]++; // total count
    if( obj2.hasOwnProperty(key) && obj2[key] === obj1[key]) {
        count[0]++; // match count
    }
}
var percentage = count[0]/count[1]*100+"%";

Of course, if your specification is different, then this won't be quite right, but it should at least get you going in the right direction.

Your question is light on details. So I will assume you want to look up values in 1 Array object and see if they occur in the 2nd Array.

You have two options.

1.) Use SQL - Convert both of them into tables and then do join on their Values. Inner join should only return things that are mon between them thus giving you a count.

2.) Use a HashMap - Convert the big Array into a Hash Map. Iterate through the small array and see if the values in the small array exist in the HashMap. If they do then you can keep a running count.

3.) Regular Array Search - Just like going through the Array normally you can see if there are matches.

本文标签: How can I calculate percentages of match between 2 Javascript objectsStack Overflow