2

With below code i was able to get duplicate but i am trying to get most recent object from each drug by using transactionDate property,Below code is only filtering duplicates any idea how to get most recent transaction for each drug.

main.js

var drugsArray =  [{
  drugName: "ADVIL",
  transactionDate: "2018-12-15"
},{
  drugName: "ADVIL",
  transactionDate: "2018-12-28"
}, 
 {
  drugName: "ATRIPLA",
  transactionDate: "2018-12-05"
},{
  drugName: "ATRIPLA",
  transactionDate: "2018-12-21"
}

];

function getDrugs(data) {

 let filtered = data.reduce((accumulator, current) => {
  if (! accumulator.find(({drugName}) => drugName === current.drugName)) {
    var checkRecentDate = getLatestDateSave(current.transactionDate)
    if(checkRecentDate) {
      accumulator.push(current);
    }

  }
  return accumulator;
}, []);

  console.log(filtered);
}


getDrugs(drugsArray);

get the recent date object using this function

function getLatestDateSave(xs) {
   if (xs.length) {
      return xs.reduce(function(m, i) {
         return (i.MeasureDate > m) && i || m;
      }, "").MeasureDate;
   }
 }

Expected output is

result = [{
        drugName: "ADVIL",
        transactionDate: "2018-12-28"
    },
    {
        drugName: "ATRIPLA",
        transactionDate: "2018-12-21"
    }

];
hussain
  • 6,587
  • 18
  • 79
  • 152

3 Answers3

4

You can approach this with reduce() method. Also, with the format you use on the dates, they can be compared direcly as strings. Example:

var drugsArray =  [
    {drugName: "ADVIL", transactionDate: "2018-12-15"},
    {drugName: "ADVIL", transactionDate: "2018-12-28"},
    {drugName: "ATRIPLA", transactionDate: "2018-12-05"},
    {drugName: "ATRIPLA", transactionDate: "2018-12-21"}
];

let result = drugsArray.reduce((res, curr) =>
{
    let exists = res.findIndex(x => x.drugName === curr.drugName);

    if (exists < 0)
        res.push(curr);
    else if (res[exists].transactionDate < curr.transactionDate)
        res[exists].transactionDate = curr.transactionDate;

    return res;
        
}, []);

console.log(result);
Shidersz
  • 16,846
  • 2
  • 23
  • 48
  • Thank you it worked perfeclty, when you get a chance please also explain what this code is doing i didnt quite understand reduce method – hussain Jan 11 '19 at 03:30
  • There is a link to documentation, I thinked you already know it because is used on your question. But basically the reduce iterates over all elements of the array while generating an accumulator. The accumulator start with the empty array `[]`. On every iteration it checks if the current element of the iteration already exists on the accumulated array, if element don't exists, we push it on the array, but if element exists, we compares the dates and update if needed. – Shidersz Jan 11 '19 at 03:39
1

You can first group the transactions into an object of arrays, then sort the dates in descending order and pick the first one:

const drugsArray = [{
    drugName: "ADVIL",
    transactionDate: "2018-12-15"
  }, {
    drugName: "ADVIL",
    transactionDate: "2018-12-28"
  },
  {
    drugName: "ATRIPLA",
    transactionDate: "2018-12-05"
  }, {
    drugName: "ATRIPLA",
    transactionDate: "2018-12-21"
  }
];

// First group the transactions into an object of arrays
const transactionMap = {};
for (const obj of drugsArray) {
  const key = obj.drugName;
  if (!transactionMap[key]) {
    transactionMap[key] = [];
  }
  transactionMap[key].push(obj);
}

// Then sort each group by transaction date and pick the first one
const result = [];
for (const obj in transactionMap) {
  transactionMap[obj].sort(function(a, b) {
    return new Date(b.transactionDate) - new Date(a.transactionDate);
  });
  result.push(transactionMap[obj][0]);
}

console.log(result);
RoadRunner
  • 25,803
  • 6
  • 42
  • 75
  • 1
    This is an effective approach, but you must ensure that data is ordered by `transactionDate`. Maybe you could add a `sort()` step at initialization just to ensure this pre-condition. – Shidersz Jan 11 '19 at 03:53
  • 1
    @Shidersz Thanks for picking that up. I ended up grouping the transactions, then sorting to get the most recent date. Although its not very efficient since you need to sort to get the max date. – RoadRunner Jan 11 '19 at 04:14
0

What I did was sort the array by transaction date and then by name. Then I took the duplicate filter method in this thread, which filters out the first item found in a duplicate set.

var drugsArray =  [{
  drugName: "ADVIL",
  transactionDate: "2018-12-15"
},{
  drugName: "ADVIL",
  transactionDate: "2018-12-28"
}, 
{
  drugName: "ATRIPLA",
  transactionDate: "2018-12-05"
},{
  drugName: "ATRIPLA",
  transactionDate: "2018-12-21"
},
{
  drugName: "AMBIEN",
  transactionDate: "2018-02-05"
},{
  drugName: "AMBIEN",
  transactionDate: "2018-12-06"
}

];

function getDrugs(){
    const output = drugsArray
    .sort(function(d1, d2){
      return new Date(d1.transactionDate) < new Date(d2.transactionDate) ? 1 : -1;
    })
    .sort(function(d1, d2){
      return d1.drugName < d2.drugName ? -1 : 1;
    })
    .filter(function(value, index, self) { 
        return index === self.findIndex(function(i){
          return i.drugName === value.drugName
        })
    });
    
    return output;
}

console.log(getDrugs());

Now this only evaluates the dates as strings. You can implicitly convert the date strings to Date objects first before comparing.

Abana Clara
  • 4,602
  • 3
  • 18
  • 31
  • this is not returning most recent dated object it returns earlier dates – hussain Jan 11 '19 at 03:15
  • @hussain 12-28 is more recent than 12-15, and then the rest are more recent. Look at it more closely. – Abana Clara Jan 11 '19 at 03:16
  • your sniipet is returning `[ { "drugName": "ADVIL", "transactionDate": "2018-12-15" }, { "drugName": "AMBIEN", "transactionDate": "2018-02-05" }, { "drugName": "ATRIPLA", "transactionDate": "2018-12-05" } ]` – hussain Jan 11 '19 at 03:16
  • It's returning `[ { "drugName": "ADVIL", "transactionDate": "2018-12-28" }, { "drugName": "AMBIEN", "transactionDate": "2018-12-06" }, { "drugName": "ATRIPLA", "transactionDate": "2018-12-21" } ]` for me what the hell. If that's the case we need to convert the strings to dates first which would take a minute. There's probably a browser issue going on – Abana Clara Jan 11 '19 at 03:17
  • I just tried here on stackOverflow and pasted the result – hussain Jan 11 '19 at 03:18
  • @hussain I converted it to a Date object. But older browsers might not support this string date formatting passed as a parameter in a Date object. You need to make a cross-browser compatible version. – Abana Clara Jan 11 '19 at 03:20