1

I have an array.

array1 = [
  {playtime: 110, date: "05 Jun"},
  {playtime: 115, date: "04 Jun"},
  {playtime: 113, date: "05 Jun"},
  {playtime: 120, date: "03 Jun"},
  {playtime: 108, date: "02 Jun"},
  {playtime: 114, date: "01 Jun"},
  {playtime: 106, date: "30 May"},
  {playtime: 90, date: "12 Jun"},
  {playtime: 89, date: "12 Jun"},
  {playtime: 89, date: "11 Jun"},
  {playtime: 95, date: "11 Jun"},
  {playtime: 99, date: "10 Jun"},
  {playtime: 98, date: "06 Jun"},
  {playtime: 96, date: "08 Jun"},
  {playtime: 120, date: "06 Jun"},
  {playtime: 102, date: "07 Jun"},
  {playtime: 120, date: "09 Jun"},
  {playtime: 190, date: "12 Jun"}
];

I have to remove the duplicates of the array1 (array with the same date are considered duplicate) and should need only the latest entry and sort the array in the descending order of the date - latest date should come first.

My first stage array should look like

array1 = [
  {playtime: 90, date: "12 Jun"},
  {playtime: 89, date: "11 Jun"},
  {playtime: 99, date: "10 Jun"},
  {playtime: 120, date: "09 Jun"},
  {playtime: 96, date: "08 Jun"},
  {playtime: 102, date: "07 Jun"},
  {playtime: 98, date: "06 Jun"},
  {playtime: 110, date: "05 Jun"},
  {playtime: 115, date: "04 Jun"},
  {playtime: 120, date: "03 Jun"},
  {playtime: 108, date: "02 Jun"},
  {playtime: 114, date: "01 Jun"},
  {playtime: 106, date: "30 May"}
];

And, then I have to splice the first 5 entries and then display from old to a new date(latest date should come last);

The final array should look like,

array1 = [
  {playtime: 106, date: "30 May"},
  {playtime: 114, date: "01 Jun"},
  {playtime: 108, date: "02 Jun"},
  {playtime: 120, date: "03 Jun"},
  {playtime: 115, date: "04 Jun"}
];

I have tried sorting with

array1.sort(function (a, b) {
  return (a.date-b.date);
});

But, got stuck.

wlh
  • 3,426
  • 1
  • 16
  • 32
aadhira
  • 321
  • 1
  • 3
  • 16
  • Is year always assumed current? – Yevhen Horbunkov Jun 26 '19 at 14:15
  • What qualifies as a duplicate? Both playtime and date values are the same? – wlh Jun 26 '19 at 14:17
  • Yeah. The year is the current year. array with the same value of `date` is considered as duplicates. – aadhira Jun 26 '19 at 14:23
  • If there are two objects with the same date and one is to be removed, which one is removed? The larger playtime? The smaller playtime? – Tor Jun 26 '19 at 14:26
  • If there are two objects with the same date , The latest `date` entry has to be retained and other `date` entries(which includes both `playtime` and `date`) has to be removed. Doesn't depend upon the `playtime`. – aadhira Jun 26 '19 at 14:32
  • There's no way sort can change the length of an array. You should use filter. You can [check this question](https://stackoverflow.com/questions/9229645/remove-duplicate-values-from-js-array) – FirstIndex Jun 26 '19 at 14:33

5 Answers5

2

What you need to do is first remove duplicates from your original array. I like the reduce function because, in this case, you need to iterate through your array to see if there is a duplicate value in the rest of the array. You check that the array does not already include that value, then push the first occurrence of that value into the returned array.

Then with sorting, you need some way to parse the date into a comparable value. Date.parse will convert the string into epoch time, and then you can compare them. (keep in mind that it is best to use an established library, such as moment to handle dates consistently across browsers.

array1.reduce((arr, obj)=>{
    if (arr.length && arr.some((o)=>o.date == obj.date)) return arr;
    arr.push(obj)
    return arr;
}, []).sort((a, b)=> {
    const d1 = Date.parse(a.date);
    const d2 = Date.parse(b.date);
    return d1 - d2;
}).splice(0,5)
wlh
  • 3,426
  • 1
  • 16
  • 32
0

//src array
const array1 = [{playtime:110,date:'05 Jun'},{playtime:115,date:'04 Jun'},{playtime:113,date:'05 Jun'},{playtime:120,date:'03 Jun'},{playtime:108,date:'02 Jun'},{playtime:114,date:'01 Jun'},{playtime:106,date:'30 May'},{playtime:90,date:'12 Jun'},{playtime:89,date:'12 Jun'},{playtime:89,date:'11 Jun'},{playtime:95,date:'11 Jun'},{playtime:99,date:'10 Jun'},{playtime:98,date:'06 Jun'},{playtime:96,date:'08 Jun'},{playtime:120,date:'06 Jun'},{playtime:102,date:'07 Jun'},{playtime:120,date:'09 Jun'},{playtime:190,date:'12 Jun'}];

const res = array1
 //remove items with repetitive date value
 .reduce((res, item) => (res.every(resItem => resItem.date != item.date) ? res.push(item) : true, res), [])
 //sort by date in ascending order
 .sort((a, b) => new Date(a.date+(new Date()).getFullYear()) - new Date(b.date+(new Date()).getFullYear()))
 //cut off 5 items
 .slice(0, 5);

console.log(res);
Yevhen Horbunkov
  • 14,965
  • 3
  • 20
  • 42
  • I didn't down vote but adding some comments to your answer so that other's can understand your logic may help. – FirstIndex Jun 26 '19 at 14:38
0

Use the following function to remove duplicates from your array :

//Your array
array1=   [{playtime: 110, date: "05 Jun"},{playtime: 115, date: "04 Jun"},{playtime: 113, date: "05 Jun"},{playtime: 120, date: "03 Jun"},{playtime: 108, date: "02 Jun"},{playtime: 114, date: "01 Jun"},{playtime: 106, date: "30 May"},{playtime: 90, date: "12 Jun"},{playtime: 89, date: "12 Jun"},{playtime: 89, date: "11 Jun"},{playtime: 95, date: "11 Jun"},{playtime: 99, date: "10 Jun"},{playtime: 98, date: "06 Jun"},{playtime: 96, date: "08 Jun"},{playtime: 120, date: "06 Jun"},{playtime: 102, date: "07 Jun"},{playtime: 120, date: "09 Jun"},{playtime: 190, date: "12 Jun"}];

//Function to remove duplicate objects from array
  function getUnique(arr, comp) {

    const unique = arr
      .map(e => e[comp])

      // store the keys of the unique objects
      .map((e, i, final) => final.indexOf(e) === i && i)

      // eliminate the dead keys & store unique objects
      .filter(e => arr[e]).map(e => arr[e]);

    return unique;
  }

//Here you will get data without duplicates
newArray = getUnique(getUnique, 'date');

Code to sort array

newArray.sort((a, b) => {
    if (a['date'] < b['date']) return -1;
    if (a['date'] > b['date']) return 1;
    return 0;
 })
Tushar
  • 1,948
  • 1
  • 13
  • 32
0

I am slightly worried that your dates exclude year and are being consumed as strings, but we can work within those constraints. This can be done by taking your array, sorting it, removing duplicates, and then returning only the first 5 elements.

// Our original array
array1 =   [
  {playtime: 110, date: "05 Jun"},
  {playtime: 115, date: "04 Jun"},
  {playtime: 113, date: "05 Jun"},
  {playtime: 120, date: "03 Jun"},
  {playtime: 108, date: "02 Jun"},
  {playtime: 114, date: "01 Jun"},
  {playtime: 106, date: "30 May"},
  {playtime: 90, date: "12 Jun"},
  {playtime: 89, date: "12 Jun"},
  {playtime: 89, date: "11 Jun"},
  {playtime: 95, date: "11 Jun"},
  {playtime: 99, date: "10 Jun"},
  {playtime: 98, date: "06 Jun"},
  {playtime: 96, date: "08 Jun"},
  {playtime: 120, date: "06 Jun"},
  {playtime: 102, date: "07 Jun"},
  {playtime: 120, date: "09 Jun"},
  {playtime: 190, date: "12 Jun"}
];

// Sort by date ascending
array1 = array1.sort(
 (a,b) => new Date(a.date) - new Date(b.date)
);

// Remove duplicates based on sorted date
var uniqueArray = [];
for(var i=0; i<array1.length; i++){
    // If we're on the first element, add it
    if(i === 0) uniqueArray.push(array1[i]);
  
    // For every subsequent element, if it's different than the last one, add it
    else if(array1[i].date !== array1[i-1].date){
   uniqueArray.push(array1[i]);
  }
}

// Then slice first 5 elements
uniqueArray = uniqueArray.slice(0, 5);

// The results match what you need
console.log(uniqueArray);
Tor
  • 784
  • 1
  • 13
  • 25
  • The answer might be cleaner if you put the `array1` on a single line at the top. The array should be nicely formatted in the question itself. People read answers for the solutions, not the input. If someone is interested in the input they should read the question instead. – 3limin4t0r Jun 26 '19 at 15:04
  • In my opinion, the array was not nicely formatted in the question itself, and is much more readable when formatted. – Tor Jun 26 '19 at 15:10
  • I agree with you that the array is not nicely formatted in the question. I merely question if an answer is the correct place to do question related markup. – 3limin4t0r Jun 26 '19 at 15:13
  • I'd argue it is - an answer is not just for the poster, but for anyone who reads it in the future, so the content should be as readable as possible. It does not change the outcome of the answer or the problem, it merely makes it readable and understandable to anyone that reads it, including the poster. – Tor Jun 26 '19 at 20:46
  • @U25lYWt5IEJhc3RhcmQg Please explain (I noticed your's didn't until you fixed it a couple of hours ago, and now it matches mine) – Tor Jun 27 '19 at 13:20
  • @Tor : in FF your code drops somewhere along the way the entry for the 30-th of May (I believe, date parsing is the issue). – Yevhen Horbunkov Jun 27 '19 at 14:00
0

Ramda.js makes this really easy to do!

const input = [
  {playtime: 110, date: "05 Jun"},
  {playtime: 115, date: "04 Jun"},
  {playtime: 113, date: "05 Jun"},
  {playtime: 120, date: "03 Jun"},
  {playtime: 108, date: "02 Jun"},
  {playtime: 114, date: "01 Jun"},
  {playtime: 106, date: "30 May"},
  {playtime: 90, date: "12 Jun"},
  {playtime: 89, date: "12 Jun"},
  {playtime: 89, date: "11 Jun"},
  {playtime: 95, date: "11 Jun"},
  {playtime: 99, date: "10 Jun"},
  {playtime: 98, date: "06 Jun"},
  {playtime: 96, date: "08 Jun"},
  {playtime: 120, date: "06 Jun"},
  {playtime: 102, date: "07 Jun"},
  {playtime: 120, date: "09 Jun"},
  {playtime: 190, date: "12 Jun"}
];

const f = R.pipe(
  R.uniqBy(R.prop("date")),
  R.sortBy(R.pipe(R.prop("date"), Date.parse)),
  R.take(5),
)

console.log(f(input))
<script src="//cdn.jsdelivr.net/npm/ramda@latest/dist/ramda.min.js"></script>
Chris Vouga
  • 555
  • 6
  • 8