包含对象的JSON行数,不包括空行

时间:2018-01-07 21:16:39

标签: javascript jquery json

我使用 API 生成访问网页所花费的平均时间,然后将所有返回值的总和除以 API 中设置的天数。

let avgtime = 0;

for (i in data) {
  if (data[i].avg_time_on_site) {
    avgtime += data[i].avg_time_on_site;
  }
}
$("#avgtime").html(avgtime / datePeriod);

datePeriod是API返回的总天数。例如,如果datePeriod设置为30,则会返回avgtime的最后30天。

avgtime += data[i].avg_time_on_site;的摘要会将 JSON 中的所有avg_time_on_site作为总和返回,并除以datePeriod以获得超过设定天数的平均值$("#avgtime").html(avgtime / datePeriod);

然而,我的问题是,只有当网页每天都有返回值时,这才有效。如果在一天内未访问该网页,如下面的示例JSON所示,avgtime将不正确,因为它将所有返回值的总和除以总天数,而不是总天数行。

{
   "2017-12-30":[],
   "2017-12-31":{
      "nb_uniq_visitors":1,
      "nb_visits":1,
      "avg_time_on_site":41,
   },
   "2018-01-01":{
      "nb_uniq_visitors":1,
      "nb_visits":2,
      "avg_time_on_site":52,
   },
   "2018-01-02":[],
   "2018-01-03":{
      "nb_uniq_visitors":1,
      "nb_visits":3,
      "avg_time_on_site":83,
   },
   "2018-01-04":[]
}

我想将datePeriod中的函数$("#avgtime").html(avgtime / datePeriod);替换为另一个计算 JSON 中总行数的函数,不包括任何没有值的日期。

我已经尝试过首先研究解决方案,但我不知所措。谢谢你的帮助。

这是我的完整脚本



setTimeout(function() {
  $('#DateSelector').val('30').trigger("change")
}, 1000);

function datePeriod() {
  let datePeriod = $("#DateSelector").val();
  $("#DateShow").html(datePeriod);
  $.getJSON(`https://discovrbookings.innocraft.cloud/?module=API&method=API.get&format=json&idSite=2&period=day&date=last${datePeriod}&token_auth=68aa5bd12137f13255dcb98794b65dff`, (data) => {
    //console.log(data);
    let avgtime = 0;

    for (i in data) {
      if (data[i].avg_time_on_site) {
        avgtime += data[i].avg_time_on_site;
      }
    }
    $("#avgtime").html(avgtime / datePeriod);
  });
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select name="DateSelector" id="DateSelector" onchange="datePeriod();">
   <option value="7">Last 7 Days</option>
   <option value="14">Last 14 Days</option>
   <option value="30">Last 30 Days</option>
   <option value="90">Last 90 Days</option>
   <option value="365">Last 365 Days</option>
</select>

<h2 id="avgtime"></h2>
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:2)

我建议您只使用另一个变量跟踪循环中的日期。这样你就可以独立于<div class="modal loop-over"></div>

datePeriod

答案 1 :(得分:0)

我建议采用不同的方法。在最终将总时间除以访问次数之前,使用map,然后reduce将数据标准化为聚合对象。

请参阅我关于使用奇数平均值的问题的说明。在这里,我提供一个给出每次访问在所提供的日期上花费的平均时间。

const avg = visits => (({cnt, time}) => time / cnt)(Object.values(visits).map(
  // Normalize to [{cnt: 0, avg: 0}, {cnt: 1, avg: 41}, ...]
  day => ({cnt: day.nb_visits || 0, avg: day.avg_time_on_site || 0})
).reduce(
  // combine to {count: 6, time: 394}
  (totals, day) => ({cnt: totals.cnt + day.cnt, time: totals.time + day.cnt * day.avg}), 
  {cnt: 0, time: 0}
))

avg(visits) //=> 65.666666666667

使用sum_visit_date代替avg_time_on_site可以略微简化:您可以跳过乘法。但那是一个小小的改变。