【问题标题】:How to filtered the duplicate values and get most recent transaction object using JS filter?如何使用 JS 过滤器过滤重复值并获取最新的交易对象?
【发布时间】:2019-06-05 23:30:49
【问题描述】:

使用下面的代码,我能够获得重复,但我试图通过使用transactionDate 属性从每种药物中获取最新对象,下面的代码仅过滤重复项,任何想法如何获取每种药物的最新交易。

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

使用此函数获取最近的日期对象

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

预期输出是

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

];

【问题讨论】:

    标签: javascript arrays angular ecmascript-6


    【解决方案1】:

    您可以使用reduce() 方法来解决此问题。此外,使用您在日期上使用的格式,它们可以直接作为字符串进行比较。示例:

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

    【讨论】:

    • 谢谢它的完美运行,当你有机会时请解释一下这段代码在做什么,我不太明白reduce方法
    • 有一个文档链接,我想你已经知道了,因为它用于你的问题。但基本上,reduce 在生成累加器的同时迭代数组的所有元素。累加器以空数组[] 开始。在每次迭代时,它检查迭代的当前元素是否已经存在于累积数组中,如果元素不存在,我们将其推送到数组中,但如果元素存在,我们会比较日期并在需要时更新。
    【解决方案2】:

    您可以先将交易分组到一个数组对象中,然后按降序对日期进行排序并选择第一个:

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

    【讨论】:

    • 这是一种有效的方法,但您必须确保数据按transactionDate 排序。也许您可以在初始化时添加sort() 步骤,以确保此前提条件。
    • @Shidersz 感谢您接受这个。我最终将交易分组,然后排序以获得最近的日期。虽然它不是很有效,因为您需要排序以获得最大日期。
    【解决方案3】:

    我所做的是按交易日期然后按名称对数组进行排序。然后我在这个thread中采用了重复过滤方法,过滤掉了在重复集中找到的第一项。

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

    现在这仅将日期评估为字符串。您可以在比较之前先将日期字符串隐式转换为 Date 对象。

    【讨论】:

    • 这不是返回最近日期的对象,而是返回较早的日期
    • @hussain 12-28 比 12-15 更新,然后其余的更新。仔细看看。
    • 你的 sniipet 正在返回 [ { "drugName": "ADVIL", "transactionDate": "2018-12-15" }, { "drugName": "AMBIEN", "transactionDate": "2018-02-05" }, { "drugName": "ATRIPLA", "transactionDate": "2018-12-05" } ]
    • 它返回[ { "drugName": "ADVIL", "transactionDate": "2018-12-28" }, { "drugName": "AMBIEN", "transactionDate": "2018-12-06" }, { "drugName": "ATRIPLA", "transactionDate": "2018-12-21" } ] 对我来说是什么鬼。如果是这种情况,我们需要先将字符串转换为日期,这需要一分钟。可能存在浏览器问题
    • 我刚刚在stackOverflow上试了一下并粘贴了结果
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-02
    • 1970-01-01
    • 1970-01-01
    • 2018-12-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多