我正在尝试对具有日期、金额和余额列的嵌套数组重新排序。余额列是预先填充的,是当天项目中订单的真实来源。
按天降序排序是第一步,但是我试图根据余额返回一天内的交易顺序是正确的。
给定下面的行"a",a.Amount + b.Balance
应等于 a.Balance
。在真实的数据集中,一天的交易少于50笔,同样的余额在一天内出现两次是非常罕见的,也许不是需要考虑的。
乱序:
[
{ date: 190105, amount: -40, balance: -10},
{ date: 190105, amount: 50, balance: 40},
{ date: 190104, amount: -20, balance: 0},
{ date: 190104, amount: 30, balance: 30},
{ date: 190103, amount: -10, balance: 20}
]
正确顺序:
[
{ date: 190105, amount: 50, balance: 40 },
{ date: 190105, amount: -40, balance: -10 },
{ date: 190104, amount: 30, balance: 30 },
{ date: 190104, amount: -20, balance: 0 },
{ date: 190103, amount: -10, balance: 20 }
]
我尝试的第一件事是如下所示的array.sort,但这不起作用,因为项目不一定需要根据下面的检查向上或向下移动,只需移动到匹配的项目的索引(如上(:
array.sort(function(a, b) {
return a.amount + b.balance - a.balance;
});
通了。
关键是排序数组中的唯一项是最后一个,因为这与我们用来查找下一个项的检查不匹配(因为它下面没有
(。因此,如果您隔离最后一项,则可以遍历其余项并在其上构建排序数组。
我认为我上面的例子与日期和多个相同的四舍五入数字有点混淆,下面工作片段中的数据更现实。
var data = [
{ order: 10, amount: -3, balance: -257 },
{ order: 4, amount: -28, balance: 1280 },
{ order: 17, amount: -344, balance: 208 },
{ order: 13, amount: -27, balance: 74 },
{ order: 1, amount: -14, balance: 1986 },
{ order: 16, amount: 5, balance: 213 },
{ order: 8, amount: -129, balance: 1659 },
{ order: 14, amount: -113, balance: 101 },
{ order: 2, amount: 800, balance: 2000 },
{ order: 9, amount: 2045, balance: 1788 },
{ order: 11, amount: -216, balance: -254 },
{ order: 6, amount: -49, balance: 1310 },
{ order: 15, amount: 1, balance: 214 },
{ order: 5, amount: -2, balance: 1308 },
{ order: 12, amount: -112, balance: -38 },
{ order: 3, amount: -80, balance: 1200 },
{ order: 7, amount: -300, balance: 1359 }
];
var sorted = [];
// the last item is the one that
// doesn't have a balance match with any other item
// and is our starting point to figuring out the order
function findLastItem(a) {
var alength = a.length;
for (var i = 0; i < alength; i++) {
var matched = false;
for (var j = 0; j < alength; j++) {
var checkBalance = a[i].amount + a[j].balance - a[i].balance;
if (checkBalance == 0) {
matched = true;
break;
}
}
if (matched === false) {
sorted.push(a[i]);
a.splice(i, 1);
break;
}
}
}
// now loop through matching transactions
// start matching against the last item we found above
// and build the sorted array bottom up
function sortItems(a) {
for (var i = a.length - 1; i >= 0; i--) {
var matched = false;
for (var j = 0; j < a.length; j++) {
var checkBalance = a[j].amount + sorted[0].balance - a[j].balance;
if (checkBalance == 0) {
sorted.unshift(a[j]);
a.splice(j, 1);
break;
}
}
}
}
findLastItem(data);
sortItems(data);
console.log(sorted);