如何根据包含最近12个月的预定义数组将值映射到数组中

4

我有一个包含数百个交易对象的数组,如下所示:

输入:

[{
    "trades": {
        "model": "Trades_Information"
        "fields": {
                "orderCloseTime": "2019-03-19T16:20:56",
                "orderOpenPrice": "1.40000",
                "orderClosePrice": "1.44000",
                "orderProfit": "75",
                "orderLots": "1.4"
        },
        [...]
}]
现在我想遍历所有对象,并将结果(包括循环中的一些计算)映射到新数组中,这些数组将更新Apexchart。 对我来说,目前最棘手的部分是动态获取正确的映射到过去12个月,因为每个新数组必须按照我如下创建的过去12个月数组的正确顺序包含值:
var date = new Date();
var lastMonths = [],
    monthNames = ['Dec', 'Nov', 'Oct', 'Sep', 'Aug', 'Jul', 'Jun', 'May', 'Apr', 'Mar', 'Feb', 'Jan'];
for (var i = 0; i < 12; i++) {
    lastMonths.push(monthNames[date.getMonth()]);
    date.setMonth(date.getMonth() - 1);
}

console.log(lastMonths);

// ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]

所以我不知怎么地,最终得到了这个简短的结构:

// Arrays needed for Apexchart
NetPipsMonth = [];
NetProfitMonth = [];
TotalVolumeMonth = [];
TotalTradesMonth = [];
lastMonths = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];

// Loop all trades in trades-object
for (var i = 0; i < tradesTotal; i++) {

    // Filter all trades by closed ones
    closeTime = trades[i].fields.orderCloseTime;
    if (closeTime != null) {

    // Make some calculations that output one value per new array per trade object


    // Push the results to each array in right order according to lastMonths array
    // Mapping with `orderCloseTime`

    }
}
我不知道如何通过orderCloseTime实现映射,以便将结果放在所需的数组中正确的位置。 我的想法是:为每个交易定义orderCloseTime的月份,并告诉JS使用lastMonths的顺序将其放置在新数组中的三月(上面的示例)处,并通过循环所有交易对象后增加其特定交易值的结果来得出月度总和。
      lastMonths = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
  NetProfitMonth = [     ,      ,  75  ,      ,      ,];
TotalVolumeMonth = [     ,      ,  1.4 ,      ,  ... ,];
  • 可以创建一个嵌套对象,在循环过程中填充此对象,以便将所有值放入一个主对象中,并在循环结束后构建apexchart所需的数组。
  • 为每个月构建12x4循环,包含每个计算,并在之后对结果进行求和,以获得包含4个数组的月度汇总(这将导致大量代码)。

期待您的想法,祝假期愉快!

2个回答

1
你确实可以按照你所建议的方式创建数组。确实,将三个值(月份、利润、销量)分组到一个对象中更符合面向对象编程的思想,但由于apexChart需要在数组中接受单独的值,直接采用这种结构就更合理。 你可以使用一些splice技巧来创建月份数组。

let tradesTotal = [{
    "trades": {
        "model": "Trades_Information",
        "fields": {
                "orderCloseTime": "2019-03-19T16:20:56",
                "orderProfit": "75",
                "orderLots": "1.4"
        },
    }
}];

let now = new Date();
now.setDate(32); // go to next month
now.setDate(1); // set to first of next month
now.setUTCHours(0, 0, 0, 0); // clear time
let firstMonth = now.getMonth();
let lastMonths = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
lastMonths.splice(0, 0, ...lastMonths.splice(firstMonth)); // rotate
let netProfitMonth = Array(12).fill(0);
let totalVolumeMonth = Array(12).fill(0);

let clone = new Date(now);
clone.setFullYear(now.getFullYear()-1);
let minDateString = clone.toJSON().slice(0, 10);
for (let {trades: { fields: { orderCloseTime, orderProfit, orderLots }}} of  tradesTotal) {
    if (orderCloseTime < minDateString) continue; // not in last 12 months: skip
    let month = (orderCloseTime.slice(5, 7) - firstMonth + 11) % 12;
    netProfitMonth[month] += +orderProfit;
    totalVolumeMonth[month] += +orderLots;
}

console.log(...lastMonths);
console.log(...netProfitMonth);
console.log(...totalVolumeMonth);


1
我会采用不同的方法。我将我的月份数组保持正常顺序。(1月到12月)。这样可以使其他数组的计算更容易。从日期中获取月份,将其用作填充数组的索引。然后计算从当前月份开始的旋转量,然后旋转您的数组。

var tradesArr = [{
  "trades": {
    "model": "Trades_Information",
    "fields": {
      "orderCloseTime": "2019-03-19T16:20:56",
      "orderOpenPrice": "1.40000",
      "orderProfit": "75",
      "orderLots": "1.4"
    }
  }
}, {
  "trades": {
    "model": "Trades_Information",
    "fields": {
      "orderCloseTime": "2019-04-19T16:20:56",
      "orderOpenPrice": "1.40000",
      "orderProfit": "75",
      "orderLots": "1.4"
    }
  }
}, {
  "trades": {
    "model": "Trades_Information",
    "fields": {
      "orderCloseTime": "2019-03-19T16:20:56",
      "orderOpenPrice": "1.40000",
      "orderProfit": "75",
      "orderLots": "1.4"
    }
  }
}, {
  "trades": {
    "model": "Trades_Information",
    "fields": {
      "orderCloseTime": "2019-05-19T16:20:56",
      "orderOpenPrice": "1.40000",
      "orderProfit": "75",
      "orderLots": "1.4"
    }
  }
}, {
  "trades": {
    "model": "Trades_Information",
    "fields": {
      "orderCloseTime": "2019-11-19T16:20:56",
      "orderOpenPrice": "1.40000",
      "orderProfit": "75",
      "orderLots": "1.4"
    }
  }
}, {
  "trades": {
    "model": "Trades_Information",
    "fields": {
      "orderCloseTime": "2019-12-19T16:20:56",
      "orderOpenPrice": "1.40000",
      "orderProfit": "75",
      "orderLots": "1.4"
    }
  }
}];

// taken from https://dev59.com/o3I-5IYBdhLWcg3wKVE9#1985471
Array.prototype.rotate = (function() {
  var unshift = Array.prototype.unshift,
    splice = Array.prototype.splice;

  return function(count) {
    var len = this.length >>> 0,
      count = count >> 0;

    unshift.apply(this, splice.call(this, count % len, len));
    return this;
  };
})();

const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; // use this and keep ordering to later.
// since the size is clear create array with size
 // fill them with 0 to claculate easier
NetPipsMonth = Array(12).fill(0);
NetProfitMonth = Array(12).fill(0);
TotalVolumeMonth = Array(12).fill(0);
TotalTradesMonth = Array(12).fill(0);

   


tradesArr.forEach(t => {
  const fields = t.trades.fields;

  const ix = new Date(fields.orderCloseTime).getMonth(); // zero indexed month
  NetProfitMonth[ix] += +fields.orderProfit;
  TotalVolumeMonth[ix] += +fields.orderLots;
  // continute
});

// assume we are on may and we want may to be last item in the array
// Date().getMonth() gave us 4 (zero indexed) 
const rotation = -((12 - 4)-1); // we need to rotate 7 to the right
   
months.rotate(rotation);
NetProfitMonth.rotate(rotation);
TotalVolumeMonth.rotate(rotation);
console.log(months, NetProfitMonth, TotalVolumeMonth);


我喜欢这种方法,但似乎结果会“延迟”一个月?例如,三月份应该有150的利润,而不是75。 - JSRB
@Phanti,我的错误。getMonth返回的是从0开始计数的月份。我以为它是从1开始计数的。 - Eldar
没问题,非常感谢。我会接受你的答案而不是其他人的(虽然其他人的也很好),因为你的更容易让我这个 JavaScript 新手理解。 - JSRB

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,