Reputation: 828
Given the two following objects:
const obj1 = {
value1: 'Hello',
value2: 'Goodbye',
value3: ['yes', 'no'],
value4: {
value5: 'Phone'
}
}
const obj2 = {
v1: 'Orange',
v2: 'Apple',
v3: ['Cat', 'Dog'],
v4: {
v5: 'Basketball'
}
}
How can I apply the keys of the first object onto the second object, assuming the structure/number of key/values is identical? Returning this:
{
value1: 'Orange',
value2: 'Apple',
value3: ['Cat', 'Dog'],
value4: {
value5: 'Basketball'
}
}
Any help would be appreciated!
Upvotes: 0
Views: 60
Reputation: 50797
I would suggest you might really want to rethink this. We can write such a function. Andrew Parks' accepted answer is one way. Here's another:
const copyStruct = (x, y, xs = Object .entries (x), ys = Object .values (y)) =>
Object .assign (
Array .isArray (x) ? [] : {},
... xs .map (([k, v], i) => ({[k]: Object (v) === v ? copyStruct (v, ys[i]) : ys[i]}))
)
const obj1 = {"value1":"Hello","value2":"Goodbye","value3":["yes","no"],"value4":{"value5":"Phone"}}
const obj2 = {"v1":"Orange","v2":"Apple","v3":["Cat","Dog"],"v4":{"v5":"Basketball"}}
console .log (copyStruct (obj1, obj2))
But, this is extremely fragile. The best way to think of Objects is as unordered collections of key-value pairs. Here you're depending upon ordering in a very tenuous manner.
For example, this really should be a no-op:
const temp = obj1 .value1
delete obj1 .value1
obj1 .value1 = temp
obj1
has the same values for the same keys as it did when it was defined. But now if you run it through either Andrew's code or mine, your result will look like this:
{
value2: "Orange",
value3: ["A", "p"],
value4: {value5: "Cat"},
value1: {v5: "Basketball"}
}
Or for another example, without our even modifying the object, our iteration order is different when the keys look like small integers:
const obj1 = {"3": "Hello", "1":"Goodbye", "2":"Phone", "4": "yes"}
const obj2 = {"5": "Orange", "6":"Apple", "4":"Basketball", "7": "cat"}
will result in:
{"1":"Basketball", "2":"Orange", "3":"Apple", "4":"cat"}
There is a possible recovery from all this mess. I'm sure your example is just dummy sample data, but if you actually have a direct relationship between the keys in the two objects, such as
const newKey = key .replace ('value', 'v')
then we could write a pretty simple recursive function to solve your problem. Otherwise, I would suggest reconsidering your approach.
Upvotes: 0
Reputation: 1974
From your problem statement, it seems like you want to modify keys of the obj2 and there is no need for obj1.
You can achieve that in a simple way using recursion:
function updateKeys(obj) {
for (let key in obj) {
const newKey = `value${key.slice(1)}`
obj[newKey] = obj[key]
delete obj[key]
if (typeof obj[newKey] === 'object' && !Array.isArray(obj[newKey])) {
updateKeys(obj[newKey])
}
}
}
updateKeys(obj2)
Upvotes: 0
Reputation: 8087
const obj1 = {"value1":"Hello","value2":"Goodbye","value3":["yes","no"],"value4":{"value5":"Phone"}}
const obj2 = {"v1":"Orange","v2":"Apple","v3":["Cat","Dog"],"v4":{"v5":"Basketball"}}
const values = (a,b,c) => (c = Object.values(b), Object.entries(a).map(([k,v],i)=>[k,v,c[i]]))
const f = (a,b) => (values(a,b).forEach(([k,v,v2])=>v instanceof Object ? f(v,v2) : a[k]=v2), a)
console.log(f(structuredClone(obj1), obj2))
Upvotes: 2