3
\$\begingroup\$

Given the JSON response below:

const result = {
  'potential': {
    A: 514,
    B: 3127,
    C: 2970,
    D: 282,
    E: 41,
    F: 1,
    undefined: 48,
  },
  'current': {
    A: 2,
    B: 961,
    C: 2897,
    D: 2568,
    E: 455,
    F: 47,
    G: 5,
    undefined: 48,
  },
};

I need to transform it to:

const temp = [
  { rating: 'A', potential: 514, current: 2 },
  { rating: 'B', potential: 3127, current: 961 },
  { rating: 'C', potential: 2970, current: 2897 },
  { rating: 'D', potential: 282, current: 2568 },
  { rating: 'E', potential: 41, current: 455 },
  { rating: 'F', potential: 1, current: 47 },
  { rating: 'G', potential: 0, current: 5 },
];

I manage by doing:

// Get unique list of keys
const allKeysSet = new Set(Object.keys(result).map(keys => Object.keys(result[keys])).flat().sort());

// Get feature names
const features = Object.keys(result);
const temp = [];

allKeysSet.forEach(s => {
  // Get features object with corresponding values, if undefined return 0
  const r = features.reduce((a, b) =>  ({ [a]: result[a][s] || 0, [b]: result[b][s] || 0 }));

  temp.push( { reference: s, ...r} );
});

console.log(temp);

If there is a simpler/efficient way of doing this, I'll appreciate it.

\$\endgroup\$
3
  • \$\begingroup\$ Welcome to Stack Review, I have two questions: I executed your code and undefined key is included in the output, it is correct ? From the example you posted it seems me the keys are always equal in potential and current, it is always the expected scenario ? \$\endgroup\$ Aug 5, 2022 at 10:22
  • \$\begingroup\$ the undefined values, could be different, but I'm removing them from temp at the moment, I keep them just in case we need to classified them in the future. \$\endgroup\$ Aug 5, 2022 at 10:27
  • \$\begingroup\$ Just a quick note: I don't see what juggling with Object.keys and Sets nets you, as you could use Object.entries to cut out most of the code for reduce. \$\endgroup\$
    – morbusg
    Aug 9, 2022 at 1:41

2 Answers 2

3
\$\begingroup\$

The first thing that can be useful to simplify your code is about the structure of the input data that contains almost the same keyset both in the potential and current properties, while the output contains the union of the two keysets. This suggests that Destructuring_assignment can help you to simplify your code, so you can unpack the potential and current properties of your initial data object into two different variables called potentialand current and obtain the union of the two keysets:

const {potential, current} = data; //<-- input data 
const allKeysSet = new Set(Object.keys(potential));
Object.keys(current).forEach(key => allKeysSet.add(key));

Your idea of using reduce and iterate over the keys of your data object is correct: you can transform your union keyset into an array with Array.from and can use the logical Nullish_coalescing_operator ?? to insert a default value (in your case 0):

const data = {
    'potential': {
      A: 514,
      B: 3127,
      C: 2970,
      D: 282,
      E: 41,
      F: 1,
    },
    'current': {
      A: 2,
      B: 961,
      C: 2897,
      D: 2568,
      E: 455,
      F: 47,
      G: 5,
    },
};
const {potential, current} = data;
const allKeysSet = new Set(Object.keys(potential));
Object.keys(current).forEach(key => allKeysSet.add(key));

const result = Array.from(allKeysSet).sort().reduce((acc, key) => {
    acc.push({'rating': key, 'potential': potential[key] ?? 0, 'current': current[key] ?? 0});
    return acc;
}, []);

console.log(result);

  

\$\endgroup\$
2
  • \$\begingroup\$ Thank you, unfortunately the G in current is lost, it needs to be set to 0 if it does not exist in one or the other \$\endgroup\$ Aug 5, 2022 at 13:04
  • \$\begingroup\$ @RicardoSanchez I made an error, I'm modifying my previous answer. \$\endgroup\$ Aug 5, 2022 at 14:45
0
\$\begingroup\$

Combine two keys from potential & current store result in keys variable array using concat, Excluding undefined value by filter and with help of map create temp array:

const result = { 'potential': { A: 514, B: 3127, C: 2970, D: 282, E: 41, F: 1, undefined: 48, }, 'current': { A: 2, B: 961, C: 2897, D: 2568, E: 455, F: 47, G: 5, undefined: 48, }, };
const {potential:potentials, current:currents} = result;
const keys = [...new Set(Object.keys(potentials).concat(Object.keys(currents)))].filter(key=>key!='undefined'); // [ "A", "B", "C", "D", "E", "F", "G" ]
const temp = keys.map(key=>({rating:key,potential:potentials[key]??0,current:currents[key]??0}));
console.log(JSON.stringify(temp, null, 4))

\$\endgroup\$
1
  • 1
    \$\begingroup\$ While this might be a good answer on stackoverflow, it is not a good answer on Code Review. A good answer on Code Review contains at least one insightful observation about the code. Alternate code only solutions are considered poor answers and may be down voted or deleted by the community. Please read How do I write a good answer. \$\endgroup\$
    – pacmaninbw
    Aug 8, 2022 at 12:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.