根据重复键过滤对象数组

时间:2019-01-20 19:41:48

标签: javascript arrays node.js

有时候,向客户收费时,会创建重复的交易。我们需要找到那些交易,以便可以对其进行处理。交易的所有内容均应相同,但交易ID和发生的时间除外,因为可能会延迟一分钟。

我需要查找所有具有相同sourceAccount,targetAccount,类别,金额的交易,并且每笔连续交易之间的时间差小于1分钟。

我一直在尝试循环数组并使用map创建一个新数组,但是我不知道如何在不提供值引用的情况下匹配该数组,因为该数组中的值是动态的,我可以不知道值。

var transac = [
  {
    id: 3,
    sourceAccount: 'A',
    targetAccount: 'B',
    amount: 100,
    category: 'eating_out',
    time: '2018-03-02T10:34:30.000Z'
  },
  {
    id: 1,
    sourceAccount: 'A',
    targetAccount: 'B',
    amount: 100,
    category: 'eating_out',
    time: '2018-03-02T10:33:00.000Z'
  },
  {
    id: 6,
    sourceAccount: 'A',
    targetAccount: 'C',
    amount: 250,
    category: 'other',
    time: '2018-03-02T10:33:05.000Z'
  },
  {
    id: 4,
    sourceAccount: 'A',
    targetAccount: 'B',
    amount: 100,
    category: 'eating_out',
    time: '2018-03-02T10:36:00.000Z'
  },
  {
    id: 2,
    sourceAccount: 'A',
    targetAccount: 'B',
    amount: 100,
    category: 'eating_out',
    time: '2018-03-02T10:33:50.000Z'
  },
  {
    id: 5,
    sourceAccount: 'A',
    targetAccount: 'C',
    amount: 250,
    category: 'other',
    time: '2018-03-02T10:33:00.000Z'
  }
];

预期:

[
  [
    {
      id: 1,
      sourceAccount: "A",
      targetAccount: "B",
      amount: 100,
      category: "eating_out",
      time: "2018-03-02T10:33:00.000Z"
    },
    {
      id: 2,
      sourceAccount: "A",
      targetAccount: "B",
      amount: 100,
      category: "eating_out",
      time: "2018-03-02T10:33:50.000Z"
    },
    {
      id: 3,
      sourceAccount: "A",
      targetAccount: "B",
      amount: 100,
      category: "eating_out",
      time: "2018-03-02T10:34:30.000Z"
    }
  ],
  [
    {
      id: 5,
      sourceAccount: "A",
      targetAccount: "C",
      amount: 250,
      category: "other",
      time: "2018-03-02T10:33:00.000Z"
    },
    {
      id: 6,
      sourceAccount: "A",
      targetAccount: "C",
      amount: 250,
      category: "other",
      time: "2018-03-02T10:33:05.000Z"
    }
  ]
];

3 个答案:

答案 0 :(得分:5)

我将为键字段创建一个组合键,并将时间转换为毫秒数,然后按这两个元素进行排序。在第二步组中,具有相同密钥且相距最多1分钟的条目:

"mywork"

在下面的评论后面,上述结果包括所有交易。具有“重复项”的重复项(根据问题中的定义)将其重复项分组在子数组中;那些没有此类重复项的变量将单独出现在其自己的子数组中。

因此,仅获取重复项,请添加适当的过滤器:

WorkManager workManager = WorkManager.getInstance();
ListenableFuture<List<WorkInfo>> workInfos = workManager.getWorkInfosByTag("mywork");

try {
    List<WorkInfo> workInfoList = workInfos.get();
    for (WorkInfo workInfo : workInfoList) {
        WorkInfo.State state = workInfo.getState();
        if (state == WorkInfo.State.ENQUEUED) {
            UUID workerId = workInfo.getId();
            Log.d(TAG, "found enqueued work with id " + workerId);
            // BUT HOW DO I TELL WHAT TIME THIS WORK IS SCHEDULED TO RUN?
        }
    }
} catch (ExecutionException e) {
    e.printStackTrace();
} catch (InterruptedException e) {
    e.printStackTrace();
}

答案 1 :(得分:1)

解决方案1 ​​ 解决方案1 ​​天真的方法-数据按日期排序,所有重复项一个接一个。

var first = reducedTransac.shift();
if (!first) {
  return [];
}
var reducedTransac = transac.reduce(function(approvedTransac, currentTrans) {
  var lastTrans = approvedTransac[approvedTransac.length - 1];
  //You'll need to write timeDiff yourself :-)
  var isTimeDiffLessThanSecond = timeDiff(lastTrans.date, currentTrans.time) >= 1;
  // Also, this can be done in many other ways, I've taken the check out of the if for code clarity, if performance is important move them inside the if...
  var isSameSourceAccount = lastTrans.sourceAccount === currentTrans.sourceAccount;
  var isSameTargetAccount = lastTrans.targetAccount === currentTrans.targetAccount;
  var isSameCategory = lastTrans.category === currentTrans.category;
  var isSameAmount = lastTrans.amount === currentTrans.amount;
  if (isTimeDiffLessThanSecond && isSameSourceAccount && isSameTargetAccount && isSameCategory && isSameAmount) {
    return approvedTransac;
  }
  approvedTransac.push(currentTrans);
  return approvedTransac;
}, [first]);

解决方案2 不了解输入顺序

var first = reducedTransac.shift();
    if(!first) {
        return [];
    }
    var transacByTimeGroupedBy = transac.reduce(function(transGroupedByTime, currentTrans) {
         var lastTransTimeGB = approvedTransac[approvedTransac.length - 1];
         var lastTrans = lastTransTimeGB[lastTransTimeGB.length - 1];

        //You'll need to write timeDiff yourself :-)
        var isTimeDiffLessThanSecond = timeDiff(lastTrans.date, currentTrans.time) >= 1;
        if(isTimeDiffLessThanSecond) {
            approvedTransac[approvedTransac.length - 1].push(lastTrans);
        } else {
            approvedTransac.concat([lastTrans])
        }
        return approvedTransac;
    }, [[first]]);

    transacByTimeGroupedBy.map(function(transactions){
        var first = transactions.shift();
        if(!first) {
            return [];
        }
        return transactions.reduce(function(approvedTransac, currentTrans) {
            var lastTrans = approvedTransac[approvedTransac.length - 1];
            var isSameSourceAccount = lastTrans.sourceAccount === currentTrans.sourceAccount;
            var isSameTargetAccount = lastTrans.targetAccount === currentTrans.targetAccount;
            var isSameCategory = lastTrans.category === currentTrans.category;
            var isSameAmount = lastTrans.amount === currentTrans.amount;
            if(isSameSourceAccount && isSameTargetAccount && isSameCategory && isSameAmount) {
                return approvedTransac;
            }
            approvedTransac.push(currentTrans);
            return approvedTransac;
         }, [first]);
    })

然后,您只需要展平最后一个数组。

未经测试的代码应非常接近您的需求。

答案 2 :(得分:1)

您可以使用以下内容:

var found=false, output=[], transac = [ { id: 3, sourceAccount: 'A', targetAccount: 'B', amount: 100, category: 'eating_out', time: '2018-03-02T10:34:30.000Z' }, { id: 1, sourceAccount: 'A', targetAccount: 'B', amount: 100, category: 'eating_out', time: '2018-03-02T10:33:00.000Z' }, { id: 6, sourceAccount: 'A', targetAccount: 'C', amount: 250, category: 'other', time: '2018-03-02T10:33:05.000Z' }, { id: 4, sourceAccount: 'A', targetAccount: 'B', amount: 100, category: 'eating_out', time: '2018-03-02T10:36:00.000Z' }, { id: 2, sourceAccount: 'A', targetAccount: 'B', amount: 100, category: 'eating_out', time: '2018-03-02T10:33:50.000Z' }, { id: 5, sourceAccount: 'A', targetAccount: 'C', amount: 250, category: 'other', time: '2018-03-02T10:33:00.000Z' } ];
    
for(i=0;i<transac.length;i++){
    j_for:for(j=0;j<output.length;j++){
        for(k=0;k<output[j].length;k++){
            if(transac[i].sourceAccount==output[j][k].sourceAccount&&transac[i].targetAccount==output[j][k].targetAccount&&transac[i].category==output[j][k].category&&transac[i].amount==output[j][k].amount&&new Date(transac[i].time).getTime()+60000>new Date(output[j][k].time).getTime()&&new Date(transac[i].time).getTime()-60000<new Date(output[j][k].time).getTime()){output[j].push(transac[i]);found=true;break j_for}
        }
    }
    if(!found){output.push([transac[i]])}
    found=false
}

console.log(output)

我希望这会对您有所帮助!