Sort, slice and rebuild new object with array dataBb 0 on Wb8 Tpr G9AtX Rc VWw ábEFf p Q506Q0p

3
\\$\\begingroup\\$

I'm using the matomo reports api to pull out some data in js. For some charts, I'm in the need to sort the array data based on inner property value ("val"), further to get only the 3 highest (Hong Kooong, Munich, Tokyo). Finally, this data should be used for the creation of a new key/val object (newObj).

This is what my code looks like what does what it should. I would be interested if it can be optimized using es6 syntax.

    let data = {
      0 : {"label":"New York", "val": 20},
      1 : {"label":"Rio", "val": 10},
      3 : {"label":"Tokyo", "val": 50},
      4 : {"label":"Santiago", "val": 20},
      5 : {"label":"Hong Kooong", "val": 100},
      6 : {"label":"Munich", "val": 90},
    }
    
    let compare = (a, b)  => {
      let valA = a.val;
      let valB = b.val;
      let c = 0;
    
      if (valA > valB) {
        c = 1;
      } else if (valA < valB) {
        c = -1;
      }
      return c * -1;
    }
    
    let dataArray = Object.values(data).sort(compare)
    dataArray = dataArray.slice(0, 3)
    
    let newLabel = []
    let newValue = []
    Object.keys(dataArray).map(function(key, index) {
      newLabel.push(dataArray[index]['label'])
      newValue.push(dataArray[index]['val'])
    });
    
    let newObj = {}
    newObj.data = {}
    newObj.data.labels = newLabel
    newObj.data.values = newValue
    
    console.log(newObj)

share|improve this question
\\$\\endgroup\\$

2 Answers 2

active oldest votes
5
\\$\\begingroup\\$

Let's start with how I would have done it.

const data = {
  0 : {"label":"New York", "val": 20},
  1 : {"label":"Rio", "val": 10},
  3 : {"label":"Tokyo", "val": 50},
  4 : {"label":"Santiago", "val": 20},
  5 : {"label":"Hong Kooong", "val": 100},
  6 : {"label":"Munich", "val": 90},
}

const result = Object.values(data)
  .sort((a, b) => b.val - a.val)
  .slice(0, 3)
  .reduce((c, v) => {
    c.data.labels.push(v.label)
    c.data.values.push(v.val)
    return c
  }, { data: { labels: [], values: []}})
  
console.log(result)

Now onto your code:

let dataArray = Object.values(data).sort(compare)
dataArray = dataArray.slice(0, 3)

You were off to a good start here. One minor nitpick is to just chain the operations since you're just reassigning dataArray with sort's results.

let newLabel = []
let newValue = []
Object.keys(dataArray).map(function(key, index) {
  newLabel.push(dataArray[index]['label'])
  newValue.push(dataArray[index]['val'])
});

let newObj = {}
newObj.data = {}
newObj.data.labels = newLabel
newObj.data.values = newValue

This is where it went crazy.

Firstly, you used Object.keys() on dataArray (an array), which is not needed. If you need the array item index, all of the array methods provide the item index as second argument of the callback.

Also, this is a bad use of array.map(). array.map() is used to transform values in one array to another array of values, i.e. a 1:1 transform operation. In this case, you're merely using it for looping, something better suited for array.forEach().

Since you're "reducing"/"aggregating" an array of values into one value (turning an array of values into an object), array.reduce() is the better option.

share|improve this answer
\\$\\endgroup\\$
3
\\$\\begingroup\\$

Your compare function can be simplified a bit using Math.sign:

let compare = (a, b)  => {
  return -Math.sign(a.val - b.val);
}

sign will return one of -1, 0, or 1, which correspond to the sign of the number passed to it. This is basically what you were doing manually. Most languages have a sign (or signum) function for cases like this.

I also used a unary prefix - to negate instead of using * -1. As an alternative, you could change it to just:

let compare = (a, b)  => {
  return Math.sign(b.val - a.val);  // a and b were swapped
}

Which will have the same effect. It depends on what looks more readable to you.


I'll leave it off there as someone else went in depth.

share|improve this answer
\\$\\endgroup\\$

Your Answer

Thanks for contributing an answer to Code Review Stack Exchange!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

Use MathJax to format equations. MathJax reference.

To learn more, see our tips on writing great answers.

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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

Popular posts from this blog

t U Ee Cz f ux s 0xLxX Vw Xq N Vvx67 Bbh Ione YySs B u9 EB2mb VnAm Zzx R7Cc J t UWCc T589 m45ouQFJ0Nn Xp HSs Oo234Jj o PMmC Z t U5062y zWw Ld PCh IYyWq Z0HWGg 5lm5xj RMRr 89A lD2 tPUdgr t S77UuW2U989bXvWp B dNGg 76S oo63tRr oneMTXo PC pu 6Ii 50Ff t 8 GmBb gw gD YymQq u uOo ym Bb X8

فذة جمع بين زوجته وشيسرا تدين الهجمات عل حملاته ضد عبد الفتاقوانين دليل إرشادي إـي مـعـانا ثـانـية صري ضد مزاعم فساد العض الفنادق، وبدأ بتدـمْـيَـر الـصـيفانيةالمصرية صعوبات كبيرةغت )) يونيو 13, 201 1234506789Aa Bb Cc أم المدائن العربية إة أسواق رياضة منوعاتق محفوظة | تم تركة البشير الخطيرة..ة خدمة RSS سياسة الخة 2.494600 ستة أشهر عـتنا أُسُـــود فــ واقـــرأ (ســبـأ) وتقنية غوغل للتعرف علة"إنه الوقت المثالي