如何使用数量和运行余额键对对象数组进行排序



我正在尝试对具有日期、金额和余额列的嵌套数组重新排序。余额列是预先填充的,是当天项目中订单的真实来源。

按天降序排序是第一步,但是我试图根据余额返回一天内的交易顺序是正确的。

给定下面的行"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);

最新更新