How to filtered the duplicate values and get most recent transaction object using JS filter?

Viewed 238

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"
    }

];
3 Answers

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);

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);

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.

Related