在相距一分钟的事务数组中查找重复项

问题描述 投票:2回答:2

挑战说明如下:

查找具有相同sourceAccount,targetAccount,类别,金额以及每个连续事务之间的时间差小于1分钟的所有事务。

输入如下:

[
  {
    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"
    }
  ]
];

我完成了排序。此代码返回一个对象数组,该键具有所有公共值,该对象并按日期排序:

function findDuplicateTransactions (transactions = []) {
return transactions.map(t => ({
    key: JSON.stringify([t.sourceAccount, t.targetAccount, t.amount, t.category]), 

    t
})).sort((a,b) => 
    a.t.time.localeCompare(b.t.time)).sort((a, b) =>a.key < b.key ? -1 : 1)}

我错过了最后一步,在这一步中,我应该互相比较并形成数组。我猜reduce是有序的,但是我不能把它包住。有人可以帮忙吗?

javascript
2个回答
0
投票

考虑Transaction是一个对象,可以教它说它是否是另一笔交易的复制品...

const transactionData = [{
    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'
  }
]


class Transaction {
  constructor(obj) {
    Object.assign(this, obj)
  }
  isDupOf(xaction) {
    return (
      this.id !== xaction.id &&  // transactions are not dups of themselves
      this.sourceAccount == xaction.sourceAccount &&
      this.targetAccount == xaction.targetAccount &&
      this.category == xaction.category &&
      this.amount == xaction.amount &&
      this.hasAboutTheSameTimeAs(xaction))

  }
  hasAboutTheSameTimeAs(xaction) {
    let msDiff = Math.abs(new Date(this.time) - new Date(xaction.time))
    return msDiff < 60000
  }
}

// transform the data into objects
const transactions = transactionData.map(d => new Transaction(d))

// this could be a static method on transaction
function isDupWithinTransactions(xaction) {
  return transactions.some(t => t.isDupOf(xaction))
}

const dups = transactions.filter(t => isDupWithinTransactions(t))
console.log(dups.sort((a,b) => a.id - b.id))

0
投票

首先使用相同的值映射数组,然后根据时间对它进行排序,如下所示:

var arr = [{
    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'
  }
];

function findDuplicateTransactions(transactions = []) {
  return transactions.reduce((ini, curr, idx) => {
    if (ini[
        curr.sourceAccount +
        curr.targetAccount +
        curr.amount +
        curr.category]) {
      ini[curr.sourceAccount + curr.targetAccount + curr.amount + curr.category]
        .push(curr);
    } else {
      ini[
        curr.sourceAccount +
        curr.targetAccount +
        curr.amount +
        curr.category] = [curr];
    }
    return ini;
  }, []);

}

var result = Object.values(findDuplicateTransactions(arr));

var expected = result.map(x => sortDate(x)).map(y => checkTimeDiff(y));

function checkTimeDiff(array) {
  var returnArr = [];
  returnArr.push(array[0]);
  for (var i = 0; i < array.length - 1; i++) {
    if ((new Date(array[i + 1].time) - new Date(array[i].time)) / 60000 <= 1) {
      returnArr.push(array[i + 1]);
    }
  }
  return returnArr;
}

function sortDate(array) {
  return array.sort(function(a, b) {
    var keyA = new Date(a.time),
      keyB = new Date(b.time);
    // Compare the 2 dates
    if (keyA < keyB) return -1;
    if (keyA > keyB) return 1;
    return 0;
  });
}
console.log(expected);

0
投票

我将使用filter函数,该函数具有用于跟踪给定参数集的最近发生的事务的映射:

function timeWindowDuplicates(props, duration) {
  const occurrences = {};
  return transaction => {
    const key = props.map(prop => transaction[prop]).join(':');
    const last = occurrences[key];
    const isDupe = last && Date.parse(transaction.time) - Date.parse(last.time) < duration;
    occurrences[key] = transaction; 
    return isDupe; 
  };
}

用法:

const dupes = source.filter(timeWindowDuplicates(
  ['sourceAccount', 'targetAccount', 'category', 'amount'], 
  60000));
© www.soinside.com 2019 - 2024. All rights reserved.