0

Given the following json array

const groups=[{ id:1, parent:null, groupName:'Others', maxScore:3}, {id:2, parent:null, groupName: 'Group 1', maxScore:0}, {id:3, parent:2, groupName:'Others, maxScore:2}, {id:4, parent:2, groupName:'Sub Group 1', maxScore:1}];

What would be a more performance oriented approach to sum maxScores within parents ? It looks like a tree structure, but nodes don't have references to their children.

Im trying a map.reduce approach right now

function addMaxScoreToGroups(groups) {
    return groups.map((group) => {
      const newGroup = group;
      if (group.parent === null && group.name !== 'Others') {
        const children = groups.filter(elem => elem.parent === group.id);
          if (children) {
            newGroup.maxScore = children.map(x => x.maxScore)
           .reduce((value, acum) => value + acum);
          }
      }
      return newGroup;
    });
}

Expected result would be

const groups=[{ id:1, parent:null, groupName:'Others', maxScore:3}, {id:2, parent:null, groupName: 'Group 1', maxScore:0,maxPosibleScore:3}, {id:3, parent:2, groupName:'Others, maxScore:2}, {id:4, parent:2, groupName:'Sub Group 1', maxScore:1}];

3
  • Questions asking for The Best.... are highly subjective. What performs best for one might not for another. You can use jsPerf or similar sites/tools to test performance on approaches/solution that work/give the correct results and use what fits your scenario best. - If you don't have a working solution yet, then re-phrase the question to focus on that instead. Commented Apr 25, 2018 at 10:35
  • It is working actually, but I think it can be optimized in terms of how many times i need to map.reduce to get the correct result. Commented Apr 25, 2018 at 11:45
  • If your code is working and you are looking for optimization codereview.stackexchange.com might get you better answers as those type of questions are usually off topic on Stackoverflow. See What Questions Are On-Topic and which ones Are not On-Topic Commented Apr 25, 2018 at 15:23

1 Answer 1

1

Iterate the with Array.reduce(). For each object create a new entry (or update existing one in case of parent) by cloning the object using object spread (or Object.assign().

If the object has a parent, create the parent if it doesn't exist, and add/update the maxPossibleScore.

Convert back to array using Object.values().

const groups=[{ id:1, parent:null, groupName:'Others', maxScore:3}, {id:3, parent:2, groupName:'Others', maxScore:2}, {id:4, parent:2, groupName:'Sub Group 1', maxScore:1}, {id:2, parent:null, groupName: 'Group 1', maxScore:5}];
    
const ms = 'maxScore';
const mps = 'maxPossibleScore';
const result = Object.values(groups.reduce((r, o) => {
  // clone
  const c = { ...o };
  
  // if current parent initalized before, update maxPossibleScore
  if(!o.parent && r[o.id]) c[mps] = r[o.id][mps] + c[ms];
  
  r[o.id] = c;
  
  if(o.parent) {
    // if parent doesn't exist init
    r[o.parent] = r[o.parent] || {};
    // if parent.maxPossibleScore doesn't exist init it
    if(!(mps in r[o.parent])) {
      r[o.parent][mps] = r[o.parent][ms] || 0;
    }
    
    r[o.parent][mps] += o[ms];
  }
  
  return r;
}, {}));

console.log(result);

Sign up to request clarification or add additional context in comments.

5 Comments

Probably @nope :)
Why? OP did ask for better performing code, why would your perform better than OPs existing code and how are you determining that? jsPerf or similar?
Big O notation - O(n) vs. at least O(n^2) (current solution). Since we're I'm using reduce, which invokes callback functions, it's less performant than a simple for loop.
@OriDrori, its not wokring :( If I just have one parent=null, its maxPosibleScore stays 0
Should be fixed now. If not, add a test case in the comments.

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.