【问题标题】:For loop sum of numbers between specific dates in array of objects对于对象数组中特定日期之间数字的循环总和
【发布时间】:2019-03-11 07:36:48
【问题描述】:

以下是来自服务器的 JSON 格式数据示例:

var infom = {
  "info": [
    {
      "date":"2018-10-04T00:00:00.000Z",
      "number":"1"
    },
    {
      "date":"2018-10-03T00:00:00.000Z",
      "number":"2"
    },
    {
      "date":"2018-10-02T00:00:00.000Z",
       "number":"3"
    },
    {
      "date":"2018-10-01T00:00:00.000Z",
      "number":"4"
    }
  ]
};
  1. 我怎样才能得到数字的总和。

    我试过了:

    info = infom.info;
    var sum = 0;
    for (var i = 0; i < info.length; i++) {
      inf = info[i];
      n1 = parseInt(inf.number);
      console.log(sum+=n1);
    }
    

    这会打印数字:1, 3, 6, 10。

    我怎样才能只得到10 而不是1, 3, 6?

  2. 如何获取特定日期之前/之后的数字。*

    例如2018-10-3之后的数字之和: 2 + 1 = 3

【问题讨论】:

  • 对于第一个问题,您需要将console.log 移到for 循环之外。对于第二个问题,您需要在元素数组上使用 .filter 并仅保留日期在您指定的日期之后/之前的那些,然后再执行添加。

标签: javascript json date for-loop sum


【解决方案1】:

重要提示:请注意来自@RobG 的评论,该评论关于在词法上比较 ISO 8601 日期字符串以避免Date.parse 出现问题的能力。请参阅下面的更新答案以反映该评论,原始答案如下供参考。

更新:

与原始示例相比,以下示例删除了日期解析步骤。

const info = {"info": [{ "date": "2018-10-04T00:00:00.000Z", "number": "1" }, { "date": "2018-10-03T00:00:00.000Z", "number": "2" }, { "date": "2018-10-02T00:00:00.000Z", "number": "3" }, { "date": "2018-10-01T00:00:00.000Z", "number": "4" } ] };
const sum = info.info.reduce((acc, obj) => {
  acc += parseInt(obj.number);
  return acc;
}, 0);

const sumDate = info.info.reduce((acc, obj) => {
  if (obj.date >= '2018-10-03T00:00:00.000Z') {
    acc += parseInt(obj.number);
  }
  
  return acc;
}, 0);

console.log('sum', sum);
console.log('sumDate', sumDate);

原文:

您需要parse the date strings 进行比较,然后您可以使用reduce。如果您更喜欢 for 循环,请参阅对原始代码的更正以及 sn-p 下方的一些快速解释(因为它仅适用于对所有值求和 - 您可以使用与下面 @ 中看到的相同原则修改 for 循环987654330@方法)。

下面的sum 只是获取对象数组中所有number 属性的总和(关于如何使用reduce 的相当简单的示例)。下面的sumDate 添加了一个if 语句来比较对象数组中的date 属性,然后将相应的number 包含在总和中(只是硬编码了2018-10-3 的日期字符串,格式与您的相同其他数据,但您可以将其转换为函数并将日期作为参数传递,并确定是否对比较日期之前或之后的日期求和)。

例如:

const info = {"info": [{ "date": "2018-10-04T00:00:00.000Z", "number": "1" }, { "date": "2018-10-03T00:00:00.000Z", "number": "2" }, { "date": "2018-10-02T00:00:00.000Z", "number": "3" }, { "date": "2018-10-01T00:00:00.000Z", "number": "4" } ] };
const sum = info.info.reduce((acc, obj) => {
  acc += parseInt(obj.number);
  return acc;
}, 0);

const sumDate = info.info.reduce((acc, obj) => {
  if (Date.parse(obj.date) >= Date.parse('2018-10-03T00:00:00.000Z')) {
    acc += parseInt(obj.number);
  }
  
  return acc;
}, 0);

console.log('sum', sum);
console.log('sumDate', sumDate);

为了纠正您最初的 for 循环尝试,主要问题是您没有增加您的 sum 变量。另外,不要忘记使用var 声明您正在使用的变量(或者使用let 或const 更好)。

var info = info.info;
var sum = 0;
for (var i = 0; i < info.length; i++) {
  sum += parseInt(info[i].number);
}

console.log(sum);
// 10

【讨论】:

  • "你需要解析日期字符串",完全不用,ISO 8601格式的字符串可以进行词法比较,避免了内置解析器的问题(您包含的参考建议避免使用)。
  • @RobG - 一如既往地感谢您的指导。答案已经过编辑,以突出显示任何未来读者的日期解析问题。
【解决方案2】:

我怎样才能只得到 10 而不是 1、3、6?

将 console.log 移出循环。还可以大大简化代码:

var infom = {"info":[
  {"date":"2018-10-04T00:00:00.000Z","number":"1"},
  {"date":"2018-10-03T00:00:00.000Z","number":"2"},
  {"date":"2018-10-02T00:00:00.000Z","number":"3"},
  {"date":"2018-10-01T00:00:00.000Z","number":"4"}
]};

var info = infom.info;
var sum = 0;

for (var i = 0; i < info.length; i++) {
  sum += parseInt(info[i].number);
}
console.log(sum);

如何获取特定日期之前/之后的数字。*

ISO 8601 格式的日期字符串可以按字典顺序进行比较。如果比较日期以相同格式提供,则避免 Date 对象和解析:

var infom = {"info":[
  {"date":"2018-10-04T00:00:00.000Z","number":"1"},
  {"date":"2018-10-03T00:00:00.000Z","number":"2"},
  {"date":"2018-10-02T00:00:00.000Z","number":"3"},
  {"date":"2018-10-01T00:00:00.000Z","number":"4"}
]};

function getSumAfter(data, date) {
  return data.reduce(function(acc, obj) {
    if (obj.date.localeCompare(date) > 0) {
      acc += +obj.number;
    }
    return acc;
  }, 0);
}

console.log(getSumAfter(infom.info,'2018-10-02T00:00:00.000Z')); // 3

// Which can be reduced to
function getSumAfter2(data, date) {
  return data.reduce((acc, obj) => obj.date.localeCompare(date) > 0? acc += +obj.number : acc, 0);
}

console.log(getSumAfter2(infom.info,'2018-10-02T00:00:00.000Z')); // 3

但是,第二个产品可能不太易于维护。

您还使用 UTC 时间戳,因此在与可能偏移并产生意外结果的“本地”日期进行比较时要小心。

【讨论】:

  • var infom = {"info":[ {"date":"2018-10-04T00:00:00.000Z","number":"1"}, {"date":" 2018-10-03T00:00:00.000Z","number":"2", "value":"1"}, {"date":"2018-10-02T00:00:00.000Z","number" :"3"}, {"date":"2018-10-01T00:00:00.000Z","number":"4"} ]};如果我想在其中包含“值”对象的数据之后/之前获取总和,该怎么办。有可能吗?
  • @uhbc—我会设置一个标志,并且只有在一个具有 value 属性的对象或具有特定属性的 value 属性时才开始对值求和值,已找到。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-19
  • 1970-01-01
  • 1970-01-01
  • 2019-02-12
相关资源
最近更新 更多