0

I am getting data from mysql. The recieved data looks like this before I parse it:

[
  { "reps": 5, "kg": 10, "exercise": "Leg Curl",    "date": "14/10/2019" },
  { "reps": 5, "kg": 10, "exercise": "Biceps Curl", "date": "15/10/2019" },
  { "reps": 5, "kg": 10, "exercise": "Dips",        "date": "16/10/2019" },
  { "reps": 5, "kg": 10, "exercise": "Dips",        "date": "16/10/2019" }
]

What I am trying to do is to sum the data that has the same exercise and date. I guess I can do a loop and sum the data, but how can I make it sum only the ones with same date and exercise?

Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
Hejhejhej123
  • 875
  • 4
  • 12
  • 25
  • 2
    Can you provide an example of how you would like the end result to look? Might be helpful to give us an idea of how to help you transform the array – Jon Warren Oct 29 '19 at 17:47
  • Does this answer your question? [Most efficient method to groupby on an array of objects](https://stackoverflow.com/questions/14446511/most-efficient-method-to-groupby-on-an-array-of-objects) – AZ_ Oct 29 '19 at 17:52

5 Answers5

2

You need to generate some sort of key lookup with making a generic key and than adding to the values.

var data = [
  {"reps":5,"kg":10,"exercise":"Leg Curl","date":"14/10/2019"},
  {"reps":5,"kg":10,"exercise":"Biceps Curl","date":"15/10/2019"},
  {"reps":5,"kg":10,"exercise":"Dips","date":"16/10/2019"},
  {"reps":5,"kg":10,"exercise":"Dips","date":"16/10/2019"}
]


var updated = Object.values(data.reduce((obj, item) => {
  var key = item.exercise + item.date
  if (!obj[key]) {
    obj[key] = Object.assign(item)
  } else {
    obj[key].reps += item.reps
  }
  return obj
}, {}))

console.log(updated)
epascarello
  • 204,599
  • 20
  • 195
  • 236
1

You can use reduce() to do that.

Iterate on given data and if an item with same date and exercise as current item exists, then add the reps, else add current item as a new entry.

let data = [{"reps":5,"kg":10,"exercise":"Leg Curl","date":"14/10/2019"},
{"reps":5,"kg":10,"exercise":"Biceps Curl","date":"15/10/2019"},
{"reps":5,"kg":10,"exercise":"Dips","date":"16/10/2019"},
{"reps":5,"kg":10,"exercise":"Dips","date":"16/10/2019"},{"reps":5,"kg":10,"exercise":"Bench Press","date":"16/10/2019"}];

let result = data.reduce((acc, curr) => {
  let item = acc.find(item => item.date === curr.date && item.exercise === curr.exercise);

  if (item) {
    item.reps += curr.reps;
  } else {
    acc.push(curr);
  }

  return acc;
}, []);

console.log(result);
Nikhil
  • 6,493
  • 10
  • 31
  • 68
1

this is better resolved with mysql, just group and sum:

SELECT sum(reps), sum(kg) FROM exercises GROUP BY date, exercise

if you want to do it with javascript, create an object with the key date and exercise filled with your data, then foreach again your data and sum the reps and kg.

Jassiel Díaz
  • 89
  • 1
  • 5
0

You could write a function that takes the desired date and exercise as strings, and adds the value to the total if they match an entry from the given array, like so:

const data = [{"reps":5,"kg":10,"exercise":"Leg Curl","date":"14/10/2019"},
{"reps":5,"kg":10,"exercise":"Biceps Curl","date":"15/10/2019"},
{"reps":5,"kg":10,"exercise":"Dips","date":"16/10/2019"},
{"reps":5,"kg":10,"exercise":"Dips","date":"16/10/2019"}];

function getTotalReps(arr, exercise, date) {
    return { exercise, date, totalReps: arr.reduce((total, entry) => {
        if (entry.exercise === exercise && entry.date === date)
            total += entry.reps;
        return total;
    }, 0) };
}

console.log(getTotalReps(data, 'Dips', '16/10/2019'));
Andre Nuechter
  • 2,141
  • 11
  • 19
0

You can reduce the data set into a new array. While looping through the items, you can locate an existing entry in the current result list by using a keying function.

var data = [
  { "reps": 5, "kg": 10, "exercise": "Leg Curl",    "date": "14/10/2019" },
  { "reps": 5, "kg": 10, "exercise": "Biceps Curl", "date": "15/10/2019" },
  { "reps": 5, "kg": 10, "exercise": "Dips",        "date": "16/10/2019" },
  { "reps": 5, "kg": 10, "exercise": "Dips",        "date": "16/10/2019" }
];

const KeyFilter = (keys) => (data) => keys.map(key => data[key]).join('|');

var exerciseFilter = KeyFilter(['date', 'exercise', 'kg']);

console.log(summarizeData(data, exerciseFilter));

function summarizeData(data, keyFn) {
  return data.reduce((results, item, index) => {
    let found = results.find(d => keyFn(d) === keyFn(item));
    if (found) {
      Object.keys(found).forEach(key => {
        let value = found[key];
        if (typeof value !== 'string') {
          found[key] += value; // Only non-string values...
        }
      });
    } else {
      results.push(item); // New entry
    }
    return results;
  }, []);
}
.as-console-wrapper { top: 0; max-height: 100% !important; }
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132