I'm trying to create an updated object from an existing object.
The sample object is:
// sample object
const testObj = {
a: 1,
b: {
c: 2,
d: {
e: 3,
f: {
g: 4
}
}
}
};
I want to create a new object from the above object with some concatenation of each value:
// expected object
const expectedObject= {
a: '1 a',
b: {
c: '2 a',
d: {
e: '3 a',
f: {
g: '4 a'
}
}
}
};
here is my sample code:
let expectedObject = {};
const newObject = object => {
Object.entries(object).forEach(([key, value]) => {
if (typeof value === "object") {
Object.keys(value).map(key => {
value[key] = value[key] + " a";
return value;
});
expectedObject[key] = value;
//return newTest;
} else {
expectedObject[key] = value;
return expectedObject;
}
});
return expectedObject;
};
console.log(newObject(testObj));
the outcome in console is:
{a: 1, b: {…}}
a: 1
b:
c: "2 a"
d: "[object Object] a"
__proto__: Object
__proto__: Object
I wanted to use recursion here and also tried it but no luck.
any help, thanks?
You could get a new object my mapping changed values and creating new objects.
function map(object, fn) {
return Object.fromEntries(Object
.entries(object)
.map(([k, v]) => [k, v && typeof v === 'object' ? map(v, fn) : fn(v)])
);
}
var object = { a: 1, b: { c: 2, d: { e: 3, f: { g: 4 } } } },
result = map(object, v => v + ' a');
console.log(result);
If you have arrays inside, you could add a check in advance and map the values.
const
map = fn => {
const iter = v => v && typeof v === 'object'
? Array.isArray(v)
? v.map(iter)
: Object.fromEntries(Object.entries(v).map(([k, v]) => [k, iter(v, fn)]))
: fn(v);
return iter;
};
var object = { a: 1, b: { c: 2, d: { e: 3, f: { g: 4, k: [5, 6] } } } },
addA = map(v => v + ' a'),
result = addA(object);
console.log(result);
This is simply a refactoring of the answer from #user633183. I like that approach a lot, but think it can be simplified by extracting two more reusable functions. This started as a comment on that answer, but I thought it would be better to be explicit.
const map = (f) => (a) =>
a.map(f)
const mapObj = (f) => (o) =>
Object .entries (o) .reduce ( (a, [k, v] ) => ({ ...a, [k]: f(v) }), {})
const traverse = (f) => (t) =>
Array.isArray(t)
? map (traverse (f)) (t)
: Object(t) === t
? mapObj (traverse (f)) (t)
: f (t)
const input =
{ a: [ 1, 11, 111 ], b: { c: 2, d: { e: [ 3, { f: { g: 4 } } ] } } }
const output =
traverse(x => `${x} a`) (input)
console.log(output)
mapObj can be written in many different ways. Here are two alternatives:
const mapObj = (f = identity) => (o = {}) =>
Object .fromEntries (Object .entries (o) .map (([ k, v ]) => [ k, f (v) ]))
const mapObj = (f = identity) => (o = {}) =>
Object .assign .apply (null, Object .entries (o) .map (([ k, v ]) => ({ [k]: f (v)
Here's an approach using a modification of the original code to demonstrate what needed to be changed in order to make it work. You had some things switched up reading the value and setting the new one. Also I'm using the spread operator to clone the object before modifying it.
const testObj = {
a: 1,
b: {
c: 2,
d: {
e: 3,
f: {
g: 4
}
}
}
};
const newObject = object => {
const clonedObj = { ...object };
const entries = Object.entries(clonedObj);
entries.forEach(([key, value]) => {
if (typeof value === "object") {
clonedObj[key] = newObject(value);
} else {
clonedObj[key] = value + " a";
}
});
return clonedObj;
};
console.log(newObject(testObj));
console.log(testObj); // prove that the original object hasn't changed
Here's a simple recursive technique. It is similar to Nina's but it preserves arrays, if present in the structure.
If the input, t, is an array, create a new array by traversing each array value, v, with the traversing function, f
(inductive) Otherwise t is not an array. If t is an object, create a new object from key value pairs, [ k, v ], by traversing each value, v, with the traversing function, f
(inductive) Otherwise t is not an array and t is not an object. This means t is either a primitive value, such as string, number, or null
Numbered comments below correspond to the explanation above -
const identity = x =>
x
const traverse = (f = identity, t = {}) =>
Array.isArray(t) // 1
? Array.from(t, v => traverse(f, v))
: Object(t) === t // 2
? Object.fromEntries(Object.entries(t).map(([ k, v ]) => [ k, traverse(f, v) ]))
: f (t) // 3
const input =
{ a: [ 1, 11, 111 ], b: { c: 2, d: { e: [ 3, { f: { g: 4 } } ] } } }
const output =
traverse(x => `${x} a`, input)
console.log(output)
Here is a solution using object-scan. It works by building the solution at the same time as the input is traversed.
// const objectScan = require('object-scan');
const testObj = { a: 1, b: { c: 2, d: { e: 3, f: { g: 4 } } } };
const cloneAndModify = (obj) => objectScan(['**'], {
breakFn: ({ property, value, isLeaf, context }) => {
if (property === undefined) {
return;
}
const ref = context[context.length - 1];
if (!(property in ref)) {
ref[property] = isLeaf ? `${value} a` : {};
}
context.push(ref[property]);
},
filterFn: ({ context }) => {
context.pop();
}
})(obj, [{}])[0];
const r = cloneAndModify(testObj);
console.log(r);
// => { b: { d: { f: { g: '4 a' }, e: '3 a' }, c: '2 a' }, a: '1 a' }
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan#13.7.1"></script>
Disclaimer: I'm the author of object-scan
Related
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));
I'm working on a project where I get an object in input like this one :
const obj = {
a: 'somestring',
b: 42,
c: {
d: 'foo',
e: 'bar'
},
f: [1, 2]
};
and I need to create some variables to get to this output :
const a = "somestring"
const b = 42
const c.d = "foo"
const c.e = "bar"
const f[0] = 1
const f[1] = 2
I got a result with this code :
for (const [k1, v1] of Object.entries(obj)) {
if (typeof v1 === "object") {
if (Array.isArray(v1)) {
for (const [k2, v2] of Object.entries(v1)) {
console.log(`const ${k1}[${k2}] = ${v2}`);
}
} else {
for (const [k2, v2] of Object.entries(v1)) {
console.log(`const ${k1}.${k2} = ${v2}`);
}
}
} else {
console.log(`const ${k1} = ${v1}`);
}
}
But when I get an object more complex like this one :
const obj = {
a: [
{
b: 'lorem'
},
{
c: 'ipsum'
}
],
d: {
e: {
f : 'foobar'
}
}
};
My output look like this :
const a[0] = [object Object]
const a[1] = [object Object]
const d.e = [object Object]
I can't find any relevant solutions. Is there a solution or npm package for this?
There is a feature called destructuring docs click here
This feature as the docs say will help you create new variables from a nested object.
Taking a object which is nested you can access its leaf values and assign them directly to vars like this:
const o = {
a: 'a',
b: {
c : 'c',
d: {
e: 'e'
}
}
};
const {a ,b : { c, d: {e} }} = o;
alert(a);
alert(c);
alert(e);
Edit: it works with arrays as well not objects only
You can do it with eval function in JS:
const obj = {
a: 'somestring',
b: 42,
c: {
d: 'foo',
e: 'bar'
},
f: [1, 2]
};
var log = console.log;
for (let key in obj) {
//log(key);
eval(`var ${key} = obj.${key}`);
}
log(a);
log(b);
log(c);
log(f);
I think you want something like this:
const obj = {
a: 'somestring',
b: 42,
c: {
d: 'foo',
e: 'bar'
},
f: [1, 2]
};
const parse = (obj, prefix = '', isArray=false) => {
Object.entries(obj).forEach(([k, v]) => {
if (typeof v === 'object') parse(v, `${k}`, Array.isArray(v))
else {
const value = (typeof v === 'string') ? `"${v}"` : v;
const before = isArray ? '[' : prefix ? '.' : '';
const after = isArray ? ']' : '';
console.log(`const ${prefix}${before}${k}${after} = ${value}`)
}
});
}
parse(obj);
I have a nested object look like this:
let obj = {
F:{
asian: {
"35-44": 1,
"55-": 1,
},
"asian/black": {
"0-24": 1,
"35-44": 1,
"45-54": 2,
},
},
M:{
asian: {
"35-44": 1,
"55-": 1,
},
white: {
"0-24": 1,
"35-44": 1,
"45-54": 2,
},
},
}
And I want to flatten the object to this:
res = {
F: 6,
M: 6,
asian: 4,
"asian/black": 4,
white: 4,
"0-24": 2,
"35-44": 4,
"45-54": 4,
"55-": 2,
}
That every value in res should be the sum of the deepest object values(F, M) and object values with the same key(0-24, 35-44...). I feel this can be done using recursion and just can't get it right. The code I write:
let returnVal = 0
const flatten = (obj, prefix = '', res = {}) => {
return Object.entries(obj).reduce((r, [key, val]) => {
if(typeof val === 'object'){
flatten(val, key, r)
} else {
res[key] = val
returnVal = val;
}
if (key in res) {
res[key] += returnVal
} else {
res[key] = 0
res[key] += returnVal
}
return r
}, res)
}
console.log(flatten(obj))
it will output:
result = {
"0-24": 2,
"35-44": 2,
"45-54": 4,
"55-": 2,
F: 2,
M: 2,
asian: 2,
"asian/black": 2,
white: 2,
}
F, M, and some other keys are not correct. Thanks!
Another, perhaps simpler, approach is as follows:
const consolidate = (obj, path = [], results = {}) =>
Object .entries (obj) .reduce ((results, [k, v]) =>
Object (v) === v
? consolidate (v, [...path, k], results)
: [...path, k] .reduce (
(results, n) => ({...results, [n] : (results[n] || 0) + v}),
results
),
results)
const data = {F: {asian: {"35-44": 1, "55-": 1}, "asian/black": {"0-24": 1, "35-44": 1, "45-54": 2}}, M: {asian: {"35-44": 1, "55-": 1}, white: {"0-24": 1, "35-44": 1, "45-54": 2}}}
console .log (consolidate (data))
.as-console-wrapper {min-height: 100% !important; top: 0}
We recursively track paths taken through the object, such as ['F', 'asian/black', '45-54'] or ['M', 'white'] or simply ['f'] as well as an object containing the final results. When we the value at the current node is an object, we recur, adding the current property name to the path. When it's not (for this data it must therefore hit a number), we hit a base case in which we take each node in the current path, and update the results object by adding that number to the value for the node in the results object, or setting it to the current value if that value doesn't exist.
There is a potential issue with the default parameters, as described in another Q & A. If someone tried to map the consolidate function directly over an array of input objects, it would fail. If this is a concern, it's easy enough to swap the default parameters for a wrapper function:
const _consolidate = (obj, path, results) =>
Object .entries (obj) .reduce ((results, [k, v]) =>
Object (v) === v
? _consolidate (v, [...path, k], results)
: [...path, k] .reduce (
(results, n) => ({...results, [n] : (results[n] || 0) + v}),
results
),
results)
const consolidate = (obj) =>
_consolidate (obj, [], {})
const data = {
F: {
asian: {
"35-44": 1,
"55-": 1,
},
"asian/black": {
"0-24": 1,
"35-44": 1,
"45-54": 2,
},
},
M: {
asian: {
"35-44": 1,
"55-": 1,
},
white: {
"0-24": 1,
"35-44": 1,
"45-54": 2,
},
},
};
const isObject = obj => Object.prototype.toString.call(obj) === "[object Object]";
function nestKeys(obj, parent = "") {
return Object.keys(obj).map(key => {
const k = parent.length ? [parent, key].join(".") : key;
if (!isObject(obj[key])) {
return k;
}
return nestKeys(obj[key], k);
}).flat();
}
function flatObj(obj) {
const map = {};
const keys = nestKeys(obj);
keys.forEach(nestedKey => {
const splited = nestedKey.split(".");
const val = splited.reduce((acc, cur) => acc[cur], obj);
splited.forEach(k => {
map[k] = (map[k] || 0) + val;
})
});
return map;
}
console.log(flatObj(data));
What is simpler pattern to avoid updating inputs if one of the keys is empty in payload ?
Is there a nice ES6 syntax ?
const master = {
inputs: {a: [], b: [], c: []}
};
const {a, b, c} = payload;
const updateMaster = (payload) => ({
...master, inputs: {...master.inputs, ...payload}
});
To filter the fields of an object, use Object.entries to retrieve the fields, Array.prototype.filter to filter then, and Object.formEntries to reconstruct an object from the filtered entries.
let payload = {
a: [],
b: [1, 2]
};
let nonEmptyPayload = Object.fromEntries(Object.entries(payload).filter(([_, v]) => v.length))
console.log(nonEmptyPayload);
Applying this to your example,
let master = {
inputs: {
a: [],
b: [13, 14],
c: [10, 12]
}
};
let trimObj = obj => Object.fromEntries(Object.entries(obj).filter(([_, v]) => v.length));
let updateMaster = payload => ({
...master,
inputs: { ...master.inputs,
...trimObj(payload)
}
});
updateMaster({
b: [15, 16], // Will override master.c
c: [] // Will not override master.c
});
console.log(master);
You could create a function like this. It removes all empty values from an object, without directly modifying the object passed to the function.
const removeEmpty = obj => {
return Object.keys(obj).reduce((acc, key) => {
// value is "falsey" or is empty array
return !obj[key] || (Array.isArray(obj[key]) && !obj[key].length)
? acc
: {...acc, [key]: obj[key]}
}, {})
}
console.log(removeEmpty({a: 'AAA', b: '', c: 'CCC', d: false, e: null, f: [1,2], g: []}))
So your final snippet would look like this:
const updateMaster = (payload) => ({
...master, inputs: {...master.inputs, ...removeEmpty(payload)}
});
I would like to know if there is a way to find the intersection of a key value pair in an array of objects. Let's say you have an array of three objects which all have the same keys like this :
arrayOfObj = [
{
"a": 1,
"b": "stringB"
"c": {"c1":1,
"c2": "stringC2"
}
},
{
"a": 1,
"b": "stringBdiff"
"c": {"c1":1,
"c2": "stringC2"
}
},
{
"a": 1,
"b": "stringB"
"c": {"c1":1,
"c2": "stringC2"
}
}
]
I would like to find the common key value pairs of the three objects:
output= [
{"a":1},
{"c": {"c1":1,
"c2":"stringC2"
}
}
]
This is what I have done so far, it works but not on nested objects. I would like to know if there is a more elegant way to do it and one that could work on nested object as well.
let properties;
let commonFound = false;
let notCommonFound = false;
const commonValues = [];
let value;
const initialArray = [{
"a": 2,
"b": "stringB",
"c": {
"c1": 1,
"c2": "stringC2"
}
},
{
"a": 1,
"b": "stringB",
"c": {
"c1": 2,
"c2": "stringC2"
}
},
{
"a": 1,
"b": "stringB",
"c": {
"c1": 2,
"c2": "stringC2"
}
}
];
const commonStorage = [];
const reference = initialArray[0];
properties = Object.keys(reference);
properties.forEach((property) => {
for (let i = 0; i < initialArray.length; i++) {
commonFound = false;
notCommonFound = false;
for (let j = 0; j <i ; j++) {
if (initialArray[i][property] === initialArray[j][property]) {
commonFound = true;
value = initialArray[i][property];
}
else {
notCommonFound = true;
value = [];
}
}
}
if (commonFound && !notCommonFound) {
commonStorage.push({[property] : value});
}
});
console.log(commonStorage);
Before we implement intersect we'll first look at how we expect it to behave –
console.log
( intersect
( { a: 1, b: 2, d: 4 }
, { a: 1, c: 3, d: 5 }
)
// { a: 1 }
, intersect
( [ 1, 2, 3, 4, 6, 7 ]
, [ 1, 2, 3, 5, 6 ]
)
// [ 1, 2, 3, <1 empty item>, 6 ]
, intersect
( [ { a: 1 }, { a: 2 }, { a: 4, b: 5 }, ]
, [ { a: 1 }, { a: 3 }, { a: 4, b: 6 }, ]
)
// [ { a: 1 }, <1 empty item>, { a: 4 } ]
, intersect
( { a: { b: { c: { d: [ 1, 2 ] } } } }
, { a: { b: { c: { d: [ 1, 2, 3 ] } } } }
)
// { a: { b: { c: { d: [ 1, 2 ] } } } }
)
Challenging problems like this one are made easier by breaking them down into smaller parts. To implement intersect we will plan to merge two calls to intersect1, each contributing one side of the computed result –
const intersect = (left = {}, right = {}) =>
merge
( intersect1 (left, right)
, intersect1 (right, left)
)
Implementing intersect1 is remains relatively complex due to the need to support both objects and arrays – the sequence of map, filter, and reduce helps maintain a flow of the program
const intersect1 = (left = {}, right = {}) =>
Object.entries (left)
.map
( ([ k, v ]) =>
// both values are objects
isObject (v) && isObject (right[k])
? [ k, intersect (v, right[k]) ]
// both values are "equal"
: v === right[k]
? [ k, v ]
// otherwise
: [ k, {} ]
)
.filter
( ([ k, v ]) =>
isObject (v)
? Object.keys (v) .length > 0
: true
)
.reduce
( assign
, isArray (left) && isArray (right) ? [] : {}
)
Lastly we implement merge the same way we did in the other Q&A –
const merge = (left = {}, right = {}) =>
Object.entries (right)
.map
( ([ k, v ]) =>
isObject (v) && isObject (left [k])
? [ k, merge (left [k], v) ]
: [ k, v ]
)
.reduce (assign, left)
The final dependencies –
const isObject = x =>
Object (x) === x
const isArray =
Array.isArray
const assign = (o, [ k, v ]) =>
(o [k] = v, o)
Verify the complete program works in your browser below –
const isObject = x =>
Object (x) === x
const isArray =
Array.isArray
const assign = (o, [ k, v ]) =>
(o [k] = v, o)
const merge = (left = {}, right = {}) =>
Object.entries (right)
.map
( ([ k, v ]) =>
isObject (v) && isObject (left [k])
? [ k, merge (left [k], v) ]
: [ k, v ]
)
.reduce (assign, left)
const intersect = (left = {}, right = {}) =>
merge
( intersect1 (left, right)
, intersect1 (right, left)
)
const intersect1 = (left = {}, right = {}) =>
Object.entries (left)
.map
( ([ k, v ]) =>
isObject (v) && isObject (right[k])
? [ k, intersect (v, right[k]) ]
: v === right[k]
? [ k, v ]
: [ k, {} ]
)
.filter
( ([ k, v ]) =>
isObject (v)
? Object.keys (v) .length > 0
: true
)
.reduce
( assign
, isArray (left) && isArray (right) ? [] : {}
)
console.log
( intersect
( { a: 1, b: 2, d: 4 }
, { a: 1, c: 3, d: 5 }
)
// { a: 1 }
, intersect
( [ 1, 2, 3, 4, 6, 7 ]
, [ 1, 2, 3, 5, 6 ]
)
// [ 1, 2, 3, <1 empty item>, 6 ]
, intersect
( [ { a: 1 }, { a: 2 }, { a: 4, b: 5 }, ]
, [ { a: 1 }, { a: 3 }, { a: 4, b: 6 }, ]
)
// [ { a: 1 }, <1 empty item>, { a: 4 } ]
, intersect
( { a: { b: { c: { d: [ 1, 2 ] } } } }
, { a: { b: { c: { d: [ 1, 2, 3 ] } } } }
)
// { a: { b: { c: { d: [ 1, 2 ] } } } }
)
intersectAll
Above intersect only accepts two inputs and in your question you want to compute the intersect of 2+ objects. We implement intersectAll as follows -
const None =
Symbol ()
const intersectAll = (x = None, ...xs) =>
x === None
? {}
: xs .reduce (intersect, x)
console.log
( intersectAll
( { a: 1, b: 2, c: { d: 3, e: 4 } }
, { a: 1, b: 9, c: { d: 3, e: 4 } }
, { a: 1, b: 2, c: { d: 3, e: 5 } }
)
// { a: 1, c: { d: 3 } }
, intersectAll
( { a: 1 }
, { b: 2 }
, { c: 3 }
)
// {}
, intersectAll
()
// {}
)
Verify the results in your browser –
const isObject = x =>
Object (x) === x
const isArray =
Array.isArray
const assign = (o, [ k, v ]) =>
(o [k] = v, o)
const merge = (left = {}, right = {}) =>
Object.entries (right)
.map
( ([ k, v ]) =>
isObject (v) && isObject (left [k])
? [ k, merge (left [k], v) ]
: [ k, v ]
)
.reduce (assign, left)
const intersect = (left = {}, right = {}) =>
merge
( intersect1 (left, right)
, intersect1 (right, left)
)
const intersect1 = (left = {}, right = {}) =>
Object.entries (left)
.map
( ([ k, v ]) =>
isObject (v) && isObject (right[k])
? [ k, intersect (v, right[k]) ]
: v === right[k]
? [ k, v ]
: [ k, {} ]
)
.filter
( ([ k, v ]) =>
isObject (v)
? Object.keys (v) .length > 0
: true
)
.reduce
( assign
, isArray (left) && isArray (right) ? [] : {}
)
const None =
Symbol ()
const intersectAll = (x = None, ...xs) =>
x === None
? {}
: xs .reduce (intersect, x)
console.log
( intersectAll
( { a: 1, b: 2, c: { d: 3, e: 4 } }
, { a: 1, b: 9, c: { d: 3, e: 4 } }
, { a: 1, b: 2, c: { d: 3, e: 5 } }
)
// { a: 1, c: { d: 3 } }
, intersectAll
( { a: 1 }
, { b: 2 }
, { c: 3 }
)
// {}
, intersectAll
()
// {}
)
remarks
You'll want to consider some things like –
intersect
( { a: someFunc, b: x => x * 2, c: /foo/, d: 1 }
, { a: someFunc, b: x => x * 3, c: /foo/, d: 1 }
)
// { d: 1 } (actual)
// { a: someFunc, c: /foo/, d: 1 } (expected)
We're testing for what's considered equal here in intersect1 –
const intersect1 = (left = {}, right = {}) =>
Object.entries (left)
.map
( ([ k, v ]) =>
isObject (v) && isObject (right[k])
? [ k, intersect (v, right[k]) ]
: v === right[k] // <-- equality?
? [ k, v ]
: [ k, {} ]
)
.filter
( ...
If we want to support things like checking for equality of Functions, RegExps, or other objects, this is where we would make the necessary modifications
recursive diff
In this related Q&A we compute the recursive diff of two objects