0

How do you combine two objects like this?

const target = { year1 : {}, year2: {somevalue2...}};
const source = { year1 : {somevalue1...}, year2: {} };

expected Input:

{ year1 : {somevalue1}, year2 : {somevalue2} }

Thank you!

Lex Dacs
  • 161
  • 3
  • 10
  • 1
    what if target and source have both a value for year1 or year2 ? do we want to combine them ? – jeremy-denis Nov 08 '22 at 15:04
  • 2
    try this? let output= { ...year1, ...year2 }; – Mat Nov 08 '22 at 15:05
  • Does this answer your question? [Merging two objects while keeping matching keys](https://stackoverflow.com/questions/59735236/merging-two-objects-while-keeping-matching-keys) – Ivar Nov 08 '22 at 15:06
  • If `target.year2`'s content should merge with and not overwrite `source.year2`, then you'll want a recursive (deep) merge. You can find a lot of information (and examples) in the answers to the following question: [How to deep merge instead of shallow merge?](https://stackoverflow.com/questions/27936772/how-to-deep-merge-instead-of-shallow-merge) – RickN Nov 08 '22 at 15:07
  • 1
    @Hunter ... of cause not since there is only `target` and `source` and in addition each features a direct `year1` and `year2` property. Thus it is not clear what ... `let output= { ...year1, ...year2 };` actually is good for and/or refers to. And regarding the useful flags of this comment, was there at least more than one second thinking about the proposed solution and its correctness/validity? – Peter Seliger Nov 08 '22 at 15:18

3 Answers3

2

Use lodash _.merge

const target = { year1 : {}, year2: {s:1}}
const source = { year1 : {s:2}, year2: {} }
const result = _.merge(target, source);
console.log('result', result)
// => { year1 : {s:2}, year2: {s:1}}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
dangarfield
  • 2,210
  • 1
  • 13
  • 18
  • Yo Thank you for your answer!. I think I forgot to mention that the objects are in array. I'm getting the data from an API which have this weird setup. Thank you dude! You save my dying brain cells lmao :D – Lex Dacs Nov 08 '22 at 15:43
1

You can use nested Array#reduce a way to look at {} as null as in the following demo:

const target = { year1 : {}, year2: {somekey2:"somevalue2"}};
const source = { year1 : {somekey1:"somevalue1"}, year2: {} };

//A function to convert any {} to null
const e2Null = obj => 
  obj && 
  Object.keys(obj).length === 0 && 
  obj.constructor === Object ? 
  null : obj;

const output = [source,target]
    .reduce((acc,cur) => Object.keys(cur)
        .reduce((a,c) => ({...a,[c]:acc[c] ?? e2Null(cur[c])}), {}),{}
    );

console.log( output );

Alternatively, you can use jQuery's .isEmptyObject(...) method as follows:

const target = { year1 : {}, year2: {somekey2:"somevalue2"}};
const source = { year1 : {somekey1:"somevalue1"}, year2: {} };

const e2Null = obj => jQuery.isEmptyObject(obj) ? null : obj

const output = [source,target]
    .reduce((acc,cur) => Object.keys(cur)
        .reduce((a,c) => ({...a,[c]:acc[c] ?? e2Null(cur[c])}), {}),{}
    );
    
console.log( output );
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
PeterKA
  • 24,158
  • 5
  • 26
  • 48
-1

You can recursively iterate over all the properties of target and source using Object.entries() or Object.keys(), and copy the properties that you want to the source or to a new object.

Something like that:

const combine = (target, source) => {
  for(const [key, value] of Object.entries(source)) {
    // here you copy the `value` to `target[key]` or
    // if the value is an object you can call `combine()` recursively
    // on the `value` and `target[key]`
  }
}
ncpa0cpl
  • 192
  • 1
  • 13