marielle
marielle

Reputation: 438

Merge two objects to obtain another object with the same structure of the first object

I need help with some data structure.

I have these objects:

const infos = {
  columnA: {color: 'red', name: 'Column Ancient' },
  columnB: {color: 'yellow', name: 'Column Blue' },
  columnC: {color: 'green', name: 'Column Consequence' },
}

const datum = { id: 0, columnA: 5, columnB: 100, columnC: 33 }

I want another object (infosWithValues) like this:

const infosWithValues = {
  columnA: {color: 'red', name: 'Column Ancient', value: 5 },
  columnB: {color: 'yellow', name: 'Column Blue', value: 100 },
  columnC: {color: 'green', name: 'Column Consequence', value: 33 },
}

This is what I tried:

const infosWithValues = [
  ...Object.entries(infos).map(([columnName, info]) => ({
    [columnName]: { ...info, value: datum[columnName] },
  })),
]

But I get:

[
  { columnA: {color: 'red', name: 'Column Ancient', value: 5 } },
  { columnB: {color: 'yellow', name: 'Column Blue', value: 100 } },
  { columnC: {color: 'green', name: 'Column Consequence', value: 33 } },
]

Upvotes: 4

Views: 453

Answers (5)

Nir Alfasi
Nir Alfasi

Reputation: 53535

I rather do it in two lines (first to copy infos and second to update the values) because it makes the code easier to read:

const infos = {
  columnA: {color: 'red', name: 'Column Ancient' },
  columnB: {color: 'yellow', name: 'Column Blue' },
  columnC: {color: 'green', name: 'Column Consequence' },
}

const datum = { id: 0, columnA: 5, columnB: 100, columnC: 33 }

// logic starts here!
infosWithValues = { ...infos }; // copy
Object.keys(infosWithValues)
      .forEach(k => infosWithValues[k].value = datum[k]); // update the values

console.log(infosWithValues);

Upvotes: 1

oleksiisedun
oleksiisedun

Reputation: 529

const infos = {
  columnA: {color: 'red', name: 'Column Ancient' },
  columnB: {color: 'yellow', name: 'Column Blue' },
  columnC: {color: 'green', name: 'Column Consequence' },
}

const datum = { id: 0, columnA: 5, columnB: 100, columnC: 33 }

const infosWithValues = Object.assign({}, infos);

Object.keys(datum).forEach(key => {
  if (infosWithValues[key]) infosWithValues[key].value = datum[key];
});

console.log(infosWithValues);

Upvotes: 0

matvs
matvs

Reputation: 1873

You almost got it right, what you need is reduce instead of map.

const infos = {
  columnA: {color: 'red', name: 'Column Ancient' },
  columnB: {color: 'yellow', name: 'Column Blue' },
  columnC: {color: 'green', name: 'Column Consequence' },
}

const datum = { id: 0, columnA: 5, columnB: 100, columnC: 33 }

const infosWithValues = Object.entries(infos).reduce((obj,[columnName, info]) => {
    obj[columnName] = { ...info, value: datum[columnName] };
    return obj;
 }, {})

console.log(infosWithValues)

Upvotes: 1

Yury Tarabanko
Yury Tarabanko

Reputation: 45106

You need to recreate object back from entries.

Object.fromEntries(Object.entries(infos).map(([key, value]) => [key, { ...value,
  value: datum[key]
}]))

const infos = {
  columnA: {
    color: 'red',
    name: 'Column Ancient'
  },
  columnB: {
    color: 'yellow',
    name: 'Column Blue'
  },
  columnC: {
    color: 'green',
    name: 'Column Consequence'
  },
}

const datum = {
  id: 0,
  columnA: 5,
  columnB: 100,
  columnC: 33
}

const result = Object.fromEntries(Object.entries(infos).map(([key, value]) => [key, { ...value,
  value: datum[key]
}]))

console.log(JSON.stringify(result))

Upvotes: 1

Nick Parsons
Nick Parsons

Reputation: 50884

You're pretty close, an easy way to get your desired result would be to spread your array of objects in a call to Object.assign() like so:

const infos = {
  columnA: {color: 'red', name: 'Column Ancient' },
  columnB: {color: 'yellow', name: 'Column Blue' },
  columnC: {color: 'green', name: 'Column Consequence' },
};

const datum = { id: 0, columnA: 5, columnB: 100, columnC: 33 };
const infosWithValues = Object.assign({}, 
  ...Object.entries(infos).map(([columnName, info]) => ({
    [columnName]: { ...info, value: datum[columnName] },
  })),
);

console.log(infosWithValues);

Or, you could use the newer Object.fromEntries() method instead which takes an array of [[key, value], ...] pairs and builds an object from that array:

const infos = {
  columnA: {color: 'red', name: 'Column Ancient' },
  columnB: {color: 'yellow', name: 'Column Blue' },
  columnC: {color: 'green', name: 'Column Consequence' },
};

const datum = { id: 0, columnA: 5, columnB: 100, columnC: 33 };
const infosWithValues = Object.fromEntries(
  Object.entries(infos).map(([columnName, info]) => 
    [columnName, { ...info, value: datum[columnName] }]
  )
);

console.log(infosWithValues);

Upvotes: 0

Related Questions