How to compare 2 objects in ES6, by key + value [duplicate] - javascript

This question already has answers here:
Object comparison in JavaScript [duplicate]
(10 answers)
Closed 1 year ago.
How can i compare 2 objects and their values using ES6?
Objects i have:
let obj1 = { c: 1, o: 1, m: 2, a: 1, s: 1 }
let obj2 = { a: 4, b: 2, c: 3, m: 2, o: 1, s: 1, d: 2 }
I want to check if obj1[key] exists in obj2. And if value of this key in obj2 same as in obj1 return true;
PS i'm kinda new to programming

I made a simple mockup with "pseudocode" comment that should help you understand
function checkObjInTables(tab1, tab2, key){
// return {KEY EXIST IN TABLE 1} AND {KEY EXIST IN TABLE 2} AND {VALUE OF KEY IN TABLE 1} IS EQUAL TO {VALUE OF KEY IN TABLE 2}
return key in tab1 && key in tab2 && tab1[key] == tab2[key];
};
let obj1 = { c: 1, o: 1, m: 2, a: 1, s: 1 }
let obj2 = { a: 4, b: 2, c: 3, m: 2, o: 1, s: 1, d: 2 }
console.log(checkObjInTables(obj1, obj2, "s")); // true
console.log(checkObjInTables(obj1, obj2, "a")); // false

Assuming the objects in the example above are not equal and that the definition of "equal" above is incomplete (and assuming we want to handle objects only) the following should work:
function equals(o1, o2) {
if (typeof o1 !== 'object' || typeof o2 !== 'object') {
return false; // we compare objects only!
}
// when one object has more attributes than the other - they can't be eq
if (Object.keys(o1).length !== Object.keys(o2).length) {
return false;
}
for (let k of Object.keys(o1)) {
if (o1[k] !== o2[k]) {
return false;
}
}
return true;
}
To clarify, according to the definition in the question the following objects are equal:
o1 = { a: 1 };
o2 = { a: 1, b: 2 };
but I find it hard to believe that this was the intention of the OP!

There is a JavaScript way.
let obj1 = { c: 1, o: 1, m: 2, a: 1, s: 1 };
let obj2 = { a: 4, b: 2, c: 3, m: 2, o: 1, s: 1, d: 2 };
const isObject = obj => typeof obj === 'object' && obj !== null;
function check(obj1, obj2) {
// check if both inputs are object and not null
if(!isObject(obj1) || !isObject(obj2)) return false;
// check if both obj has equal size
if(Object.keys(obj1) !== Object.keys(obj2)) return false;
for (const key of Object.keys(obj1)) {
if (!(key in obj2) || obj1[key] !== obj2[key]) return false;
}
return true;
}
console.log(check(obj1, obj2));

Related

How to remove duplicate value from object in Javascript

let obj = { T: 1, h: 1, i: 3, s: 3, t: 1, r: 1, n: 1, g: 1 };
In the given object we have 2 keys(i & s both have same value 3) contains same value. I need to keep one key/value pair and another wants to remove.
How we can achieve this?
Make a copy and leave one field out?
let obj2 = { T: obj.T, h: obj.h, i: obj.i, t: obj.t, r: obj.r, n: obj.n, g: obj.g };
;-)
It's not super clear if you want to omit all keys with duplicate values or just some keys. In case you want the latter, here's a reusable function for that:
function copyWithout(source, ...keysToOmit) {
return Object.entries(source).reduce(
(accumulator, [key, value]) => {
return keysToOmit.includes(key)
? accumulator
: Object.assign(accumulator, { [key]: value });
},
Object.create(null) // or just {}
);
}
And use it like so:
copyWithout(obj, 'i');
Can be used to omit multiple keys as well:
copyWithout(obj, 'i', 't', 'r');
You can loop over object keys and add values in some temp array. Verify from that temp array and if value already exist in it then delete that key from object. Try like below.
let obj = { T: 1, h: 1, i: 3, s: 3, t: 1, r: 1, n: 1, g: 1 };
let val = [];
// loop over keys and verify that if value is repeating then delete that key from object.
Object.keys(obj).forEach(k => {
if (val.includes(obj[k])) {
delete obj[k];
} else {
val.push(obj[k])
}
});
console.log(obj);
Alternatively if you wish to keep your object as it is and want output in another object then try like below.
let obj = { T: 1, h: 1, i: 3, s: 3, t: 1, r: 1, n: 1, g: 1 };
let val = [];
let newObj = {};
// loop over keys and verify that if value is repeating then delete that key from object.
Object.keys(obj).forEach(k => {
if (!Object.values(newObj).includes(obj[k])) {
newObj[k] = obj[k];
}
});
console.log('newObj', newObj);
console.log('obj', obj);
You can use the following and swap key values twice,
let obj = { T: 1, h: 1, i: 3, s: 3, t: 1, r: 1, n: 1, g: 1 };
function swapKV(ob) {
return Object.entries(ob).reduce((p,[key,value]) => ({...p,[value]: key}),{})
}
swapKV(swapKV(obj))
You could save all unique values in set. This is the most optimal solution since it takes O(n) in time.
let obj = { T: 1, h: 1, i: 3, s: 3, t: 1, r: 1, n: 1, g: 1 };
function removeDuplicateValues(obj) {
const uniqueValues = new Set();
const uniquePairs = {};
Object.keys(obj).forEach(key => {
const curValue = obj[key];
if (!uniqueValues.has(curValue)) {
uniqueValues.add(curValue);
uniquePairs[key] = curValue;
}
});
return uniquePairs;
}
console.log(removeDuplicateValues(obj)) // {T: 1, i: 3}
const object = { a: 1, b: 2, c: 3, d: 2, e: 3 };
const removeUniqueValuesFromObject = (object) => {
const map = new Map();
// loop through all the attributes on an object
for (const [key, value] of Object.entries(object)) {
// check if the value already exists in map, if yes delete the attribute
if (map.has(value)) {
delete object[`${key}`];
continue;
}
// if value not found, add it to the map
map.set(value, key);
}
// return the updated object
return object;
};
const result = removeUniqueValuesFromObject(object);
console.log(result);

How to swap key-value and only return the first pair in javascript?

Here is the task
#param {object} ???
#returns {object} an object with the given object's values as keys, and keys as values. If there are duplicate values in the input object, only the first key-value pair should be used and subsequent pairs with the same value discarded.
2.Here is what i did code
What's wrong with it? How should i rework?
const object5 = { a: 1, b: 2, c: 3, d: 1 };
const object6 = { a: 1, b: 1, c: 1, d: 1 };
function swapPairs2(obj){
let newObject = {};
for(const key in obj){
let value = obj[key]
newObject[value] = key;
}
return newObject;
}
3.Here are the tests
test(swapPairs2(object5), { 1: "a", 2: "b", 3: "c" });
test(swapPairs2(object6), { 1: "a" });
4.Here is the error i got
I am supposed to get the first key-value pair, but a random return.
You can also reverse the entries.
const object5 = { a: 1, b: 2, c: 3, d: 1 };
const object6 = { a: 1, b: 1, c: 1, d: 1 };
const swapPairs2 = obj => Object.fromEntries(
Object.entries(obj)
.reverse() // Keep the first, not the last
.map(entry => [entry[1], entry[0]]) // Reverse the key and vlaue
);
console.log(swapPairs2(object5));
console.log(swapPairs2(object6));
Only add the value/key pairs, if the value doesn't already exist on newObject by checking with the in operator:
function swapPairs2(obj) {
const newObject = {};
for (const key in obj) {
const value = obj[key];
if(!(value in newObject)) {
newObject[value] = key;
}
}
return newObject;
}
const object5 = { a: 1, b: 2, c: 3, d: 1 };
const object6 = { a: 1, b: 1, c: 1, d: 1 };
console.log(swapPairs2(object5));
console.log(swapPairs2(object6));
Another option is to use Array.reduce():
const swapPairs2 = obj =>
Object.entries(obj)
.reduce((acc, [k, v]) =>
v in acc
? acc
: { ...acc, [v]: k }
, {})
const object5 = { a: 1, b: 2, c: 3, d: 1 };
const object6 = { a: 1, b: 1, c: 1, d: 1 };
console.log(swapPairs2(object5));
console.log(swapPairs2(object6));
You can do it by taking the object keys and using the Array.reduce() method on the keys.
const object5 = { a: 1, b: 2, c: 3, d: 1 };
const object6 = { a: 1, b: 1, c: 1, d: 1 };
const swapPairs2 = (obj) => Object.keys(obj)
.reduce((a, c) => (a[obj[c]] = a[obj[c]] ?? c, a), {});
console.log(swapPairs2(object5));
console.log(swapPairs2(object6));
Or using the Array.reduce() method on the Object.entries()
const object5 = { a: 1, b: 2, c: 3, d: 1 };
const object6 = { a: 1, b: 1, c: 1, d: 1 };
const swapPairs2 = obj => Object.entries(obj)
.reduce((acc, [key, val]) => (acc[val] = acc[val] ?? key, acc), {})
console.log(swapPairs2(object5));
console.log(swapPairs2(object6));

How can I unite multiple objects to add their keys?

Implement the sumObjects function, which takes an unlimited number of objects and returns an object that combines all the objects entered.
Notes:
All object properties will have numeric values only
If the object keys match, the values of the corresponding keys are summed
The function always returns an object
The numbers in the object can be positive or negative
You can use the rest operator to collect arguments passed to a function in one array
Examples:
const obj = {};
sumObjects() === {}
sumObjects(obj) === {}
and
const first = {a: 2, b: 4};
const second = {a: 2, b: 10};
const third = {d: -5};
sumObjects(first) === {a: 2, b: 4}
sumObjects(first, third) === {a: 2, b: 4, d: -5}
sumObjects(first, second, third) === {a: 4, b: 14, d: -5}
This is my code.
function sumObjects(...params) {
let C = Object.fromEntries(
Object.keys(params[0])
.concat(Object.keys(params[1]))
.map(k => [k,
(params[0][k] || 0) + (params[1][k])
])
)
return C
}
I don't know how to add all these objects into one.
The bottom line is that I need to combine all the objects, but I just don't know how to do this, I can't find anything.
You can iterate over the param objects using .reduce and for each object, set/update its properties in acc:
function sumObjects(...params) {
return params.reduce((acc,item) => {
Object.entries(item).forEach(([property,value]) => {
const prev = acc[property];
acc[property] = prev ? prev+value : value;
});
return acc;
}, {});
}
const first = { a: 2, b: 4 };
const second = { a: 2, b: 10 };
const third = { d: -5 };
console.log( sumObjects(first) );
console.log( sumObjects(first, third) );
console.log( sumObjects(first, second, third) );
You could reduce the array of objects and iterate the entries of a single object.
const
sumObjects = (...objects) => objects.reduce((r, o) => {
Object.entries(o).forEach(([k, v]) => r[k] = (r[k] ||0) + v);
return r;
}, {}),
first = { a: 2, b: 4 },
second = { a: 2, b: 10 },
third = { d: -5 };
console.log(sumObjects(first)); // {a: 2, b: 4}
console.log(sumObjects(first, third)); // {a: 2, b: 4, d: -5}
console.log(sumObjects(first, second, third)); // {a: 4, b: 14, d: -5}
.as-console-wrapper { max-height: 100% !important; top: 0; }

Return an Array of Arrays containing objects that share a common value in a property

Say I have an array of 3 objects like this:
[
{
a: 4,
b: 5,
c: 4
},
{
a: 3,
b: 5,
c: 6
},
{
a: 2,
b: 3,
c: 3
}
]
I would like to return an array of arrays containing the objects that share a common value for the property b. So the resulting array would contain only one array containing 2 objects like this:
[
[
{
a: 4,
b: 5,
c: 4
},
{
a: 3,
b: 5,
c: 6
}
]
]
How would I do this?
You could do this with map and filter
var data = [{"a":4,"b":5,"c":4},{"a":3,"b":5,"c":6},{"a":2,"b":3,"c":3}];
var check = data.map(e => {return e.b});
var result = [data.filter(e => { return check.indexOf(e.b) != check.lastIndexOf(e.b)})];
console.log(result)
To group multiple objects in separate arrays with same b values you can use map and forEach
var data = [{"a":4,"b":5,"c":4},{"a":3,"b":5,"c":6},{"a":2,"b":3,"c":3}, {"a":3,"b":7,"c":6},{"a":2,"b":7,"c":3}], result = [];
var check = data.map(e => {return e.b});
data.forEach(function(e) {
if(check.indexOf(e.b) != check.lastIndexOf(e.b) && !this[e.b]) {
this[e.b] = [];
result.push(this[e.b]);
}
(this[e.b] || []).push(e);
}, {});
console.log(result)
This proposal uses a single loop with Array#forEach but without Array#indexOf.
var array = [{ a: 4, b: 5, c: 4 }, { a: 3, b: 5, c: 6 }, { a: 2, b: 3, c: 3 }],
grouped = [];
array.forEach(function (a) {
this[a.b] = this[a.b] || [];
this[a.b].push(a);
this[a.b].length === 2 && grouped.push(this[a.b]);
}, Object.create(null));
console.log(grouped);
You can create a function that accepts fulfillment criteria and will return as many nested arrays as rules passed.
Let's say you have an array of objects, arr.
var arr = [{a: 1, b: 2}, {a: 3, b: 2}, {a: 3, b: 4}, {a: 1, b: 1}]
And you want to return an array with with nested arrays that fulfill a particular requirement, let's say you want objects with an a:1 and b:2.
You can create a function that loops through your rules and creates a nested array with the objects that fulfill each rule.
For example:
var arr = [{a: 1, b: 2}, {a: 3, b: 2}, {a: 3, b: 4}, {a: 1, b: 1}]
function makeNestedArrays() {
var rules = [].slice.call(arguments);
return rules.reduce(function(acc, fn) {
var nestedArr = [];
arr.forEach(function(obj) {
if (fn(obj)) {
nestedArr.push(obj);
}
});
// only push nested array
// if there are matches
if (nestedArr.length) {
acc.push(nestedArr);
}
return acc;
}, []);
}
var result = makeNestedArrays(
function(obj) { return obj.a === 1; },
function(obj) { return obj.b === 2; }
);
console.log(result);
This allows you to pass as many "rules" as you want, and will create a nested array for each rule so long as there is at least one match.
You could use a Map to group them, this should work with any kind of value (just be sure the equality rules check out):
var arr = [{
a: 4,
b: 5,
c: 4
}, {
a: 3,
b: 5,
c: 6
}, {
a: 2,
b: 3,
c: 3
}];
var result = arr.reduce(function(m, o){
var value = o.b;
if(m.has(value)){
m.get(value).push(o);
} else {
m.set(value, [o]);
}
return m;
}, new Map());
console.log(...(result.values()));
If you'd need to filter out the groups of 1:
var arr = [{
a: 4,
b: 5,
c: 4
}, {
a: 3,
b: 5,
c: 6
}, {
a: 2,
b: 3,
c: 3
}];
var result = arr.reduce(function(m, o){
var value = o.b;
if(m.has(value)){
m.get(value).push(o);
} else {
m.set(value, [o]);
}
return m;
}, new Map());
result = [...result.values()].filter(a => a.length > 1);
console.log(result);

Getting keys of an object that has same values

I have an object like:
Object {v: 1, b: 1, n: 1, m: 1, c: 2, d: 3}
I am trying to collect keys that has same values and generate an array (so in this case [v, b, n, m].
So if I know 1, how can I get v,b,n,m in an array?
You can use Object.keys() to get key values of the object, then filter values based on your condition using filter()
var obj = {
v: 1,
b: 1,
n: 1,
m: 1,
c: 2,
d: 3
},
val = 1;
var res = Object.keys(obj).filter(function(v) {
return obj[v] == val;
});
document.write('<pre>' + JSON.stringify(res, null, 4) + '</pre>');
Performance? Simple for...in loop.
var myObj = {v: 1, b: 1, n: 1, m: 1, c: 2, d: 3};
function collect (obj, value) {
var arr = [];
for (var key in obj)
if (obj.hasOwnProperty(key) && obj[key] === value)
arr.push(key);
return arr;
}
console.log(collect(myObj, 1));
Fancy? Object.keys, and Array.prototype.filter.
var myObj = {v: 1, b: 1, n: 1, m: 1, c: 2, d: 3};
function collect (obj, value) {
return Object.keys(obj).filter(key => obj[key] === value);
}
console.log(collect(myObj, 1));
using the underscore.js library you can do the following
var object = {v: 1, b: 1, n: 1, m: 1, c: 2, d: 3};
var output = _.map(object, function(value, key){
if(value == 1){
return key
}
}).filter(function(value){
return value;
});
console.log(output);

Categories

Resources