挑战说明如下:
查找具有相同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是有序的,但是我不能把它包住。有人可以帮忙吗?
考虑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))
首先使用相同的值映射数组,然后根据时间对它进行排序,如下所示:
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);
我将使用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));