0

I am trying to take this array :

[
   {
      "date": a timestamp:  June 20, 2020 at 7:32:42 PM UTC
      "value": 3
      ..
   }
..
]

and accomplish 3 things effeciently

  1. Convert the timestamp to normal date and replace with the timestamp
  2. Merge dates of the same day. ( so i add their values and set under a single day.
  3. Sort the array when recent are first.

I have started with something like this :

array.sort(function(a,b){ return  new Date(b.date) - new Date(a.date);

var salesDates = sales.map(function(element){element.date = new Date(element.date); return element }); });

Which will only sort, but i need to replace timestamp/date, sort and merge same dates elegantly and effeciently

Is it possible with only sort function ?

paul seems
  • 505
  • 4
  • 12
  • 2
    do you have some data and the wanted result? – Nina Scholz Jul 06 '20 at 08:13
  • I just have 2 data points, so i can write a real date there if it helps, otherwise, please let me know what's not clear about the desired result ? array of objects with dates, latest first, and dates of the same day are combined to a single date with sum values. – paul seems Jul 06 '20 at 08:19
  • "*Is it possible with only `sort` function ?*" no, it's not. `.sort()` will *only* sort. If you try to do any other modifications of the underlying array, you are extremely likely to get incorrect results. You can merge -> sort, or transform -> merge -> sort (the steps can also be in different order) which would be the simplest to read. You can also combine all of this at once but you'd have to implement the sorting yourself to directly produce a sorted result. This would likely be more efficient but harder to implement and maintain. – VLAZ Jul 06 '20 at 08:19
  • So 3 different functions ? say i sort first, then replace dates, and how would i combine same days ? – paul seems Jul 06 '20 at 08:22
  • You would like to sort according to the dates and combine them on the same date. Isn't it? – Shahnawaz Hossan Jul 06 '20 at 08:24
  • can you add your desire output in question? – Vinay Jul 06 '20 at 08:25

2 Answers2

2

Here. First i group it with .reduce(). Then i sort it .sort(). After that i change the timestamp to a date format.

let arr = [
   {
      "date": 1594023899426,
      "value": 3
   },
   {
      "date": 1592423499234,
      "value": 2
   },
   {
      "date": 1594023899426,
      "value": 1
   }
];

let result = arr
  .reduce((a, v) => {
    let index = a.findIndex(el => el.date === v.date);
    if (index !== -1) {
      a[index].value += v.value;
      return a;
    }
    a.push({
      date: v.date,
      value: v.value
    });
    return a;
  }, [])
  .sort((a, b) => b.date - a.date)
  .map(el => {
    el.date = new Date(el.date);
    return el;
  });


console.log(result);
bill.gates
  • 14,145
  • 3
  • 19
  • 47
1

Here's another approach to it:

let sortingReducer = (accumulator, obj) => {
  // This is the merging logic
  let existingObj = accumulator.find(
    (compareObj) => {
      return obj.date?.getDate() === compareObj.date?.getDate()
    }
  );
  if (existingObj) {
    existingObj.value += obj.value;
    return accumulator;
  }

  // This is the sorting logic
  const nextIndex = accumulator.findIndex(
    (compareObj) => obj.date?.getTime() < compareObj.date?.getTime()
  );
  const index = nextIndex > -1 ? nextIndex : accumulator.length;
  accumulator.splice(index, 0, obj);
  
  return accumulator;
};

const input = [
  {
    date: new Date(),
    value: 2,
  },
  {
    date: new Date(new Date().setDate(1)),
    value: 4,
  },
  {
    date: new Date(new Date().setDate(1)),
    value: 1,
  },
  {
    date: new Date(new Date().setDate(2)),
    value: 7,
  },
];

const output = input.reduce(sortingReducer, []);

I've take some help from this answer: https://stackoverflow.com/a/50246275/1912288

I like the approach in the above answer, this is just a different approach to it.

abhim
  • 1,126
  • 1
  • 9
  • 19