【问题标题】:JSON loop and add sum to variableJSON循环并将总和添加到变量
【发布时间】:2017-01-21 21:30:41
【问题描述】:

我一直在使用 GitHub API 并尝试将每个 repo 的语言分开。我有两个主要问题:

  1. 在“for 循环”之外访问完整列表
  2. 添加循环输出以创建总和

这是我到目前为止所得到的:

function repoLanguage(repoName, divId) {
  var repo = repoName;
  var div = divId;

  function languages() {
    var responseObj = JSON.parse(this.responseText);
    for(x in responseObj) {
      var lang = x;
      var percent = Math.round(responseObj[x]/33256*1000) /10;
      var results = lang + "(" + percent + "%), ";
      document.getElementById(div).innerHTML += results;
    }
    // Cut string of trailing comma and add period.
    var str = document.getElementById(div).innerHTML;
    var cutStr = str.slice(0, -2) + ".";
    document.getElementById(div).innerHTML = cutStr;
  }
  // JSON http Request
  var request = new XMLHttpRequest();
  request.onload = languages;
  request.open('GET', 'https://api.github.com/repos/DubDJ/'+repo+'/languages', true);
  request.send();
};

repoLanguage('chat-with-alex', 'languages');
<div id="languages"></div>

基本上,我想用变量总数替换静态总数,但我无法添加 JSON 文件的所有值。

for(x in responseObj) {
      var lang = x;
      var total = responseObj[x];
      var percent = Math.round(responseObj[x]/total*1000) /10;
      var results = lang + "(" + percent + "%), ";
      document.getElementById(div).innerHTML += results;
    }

我尝试将总数移到语言函数之外,但它每次只返回最后一个值。我尝试了total += responseObj[x]total = responseObj[x]++ 以及许多其他方法,但我无法得到解决方案。我用谷歌搜索并没有运气。希望有懂行的大侠指教。

【问题讨论】:

    标签: javascript json api for-loop


    【解决方案1】:

    遍历对象一次以计算百分比之前的总数:

    var total = 0;
    for (var lang in responseObj)
        if(responseObj.hasOwnProperty(lang))
            total += responseObj[lang];
    console.log(total);
    

    【讨论】:

    • 这解决了这个问题,但对于为什么某些事情在 JavaScript 中的运作方式仍然有些困惑,感谢您花时间回答。
    【解决方案2】:

    您之前可能可以在单独的循环中计算总行数。

    function repoLanguage(repoName, divId) {
      var repo = repoName;
      var div = document.getElementById(divId);
    
      function languages() {
          var responseObj = JSON.parse(this.responseText);
          console.log('initial resoponse is', responseObj);
          //first let's get total number of strings
          // by summing the lines from all languages
          var total = 0;
          for (x in responseObj) {
            if (!responseObj.hasOwnProperty(x)) continue;
            total += responseObj[x];
          }
          //then use it
          for (x in responseObj) {
            var lang = x;
            var percent = Math.round(responseObj[x] / total * 1000) / 10;
            var results = lang + "(" + percent + "%), ";
            div.innerHTML += results;
          }
          // Cut string of trailing comma and add period.
          var str = div.innerHTML;
          var cutStr = str.slice(0, -2) + ".";
          div.innerHTML = cutStr;
        }
        // JSON http Request
      var request = new XMLHttpRequest();
      request.onload = languages;
      request.open('GET', 'https://api.github.com/repos/DubDJ/' + repo + '/languages', true);
      request.send();
    };
    
    repoLanguage('chat-with-alex', 'languages');
    <div id="languages"></div>

    你从 github api 得到的,它是一个 JSON 响应。使用JSON.parse 方法,您可以将其转换为Object

    { "HTML": 21934,
      "CSS": 6402,
      "JavaScript": 4412,
      "PHP": 508 }
    

    Keys(property names) 这个对象的名称表示语言名称,属性值表示以特定语言编写的行数(因此项目中有 2193 行 HTML,6402 行 CSS 等)。百分比计算公式的总行数应该是所有语言行数的总和。要对所有值求和,您需要一个额外的循环:

    var total = 0;
    for (x in responseObj) {
      if (!responseObj.hasOwnProperty(x)) continue;
      total += responseObj[x];
    }
    

    如果您尝试以相同的 loop 求和(尽管您使用的语言),您将仅获得 HTML (21934) 的第一次迭代值,然后是 CSS (6402) 等。因此您将仅获得全部金额到整个循环结束。 要检查这一点,您可以debug,或在您感兴趣的变量上临时使用console.log(yourVariable),以查看在执行代码期间这些内容是如何真正改变的。

    使用 ES7,您将能够使用 Object.valuesObject.entries 代替:

        function repoLanguage(repoName, divId) {
          let repo = repoName;
          let div = document.getElementById(divId);
    
          function languages() {
              let responseObj = JSON.parse(this.responseText);
              //first let's get total number of strings
              let total = Object.values(responseObj).reduce((acc, v) => acc += v, 0);
              //then use it
              Object.entries(responseObj).forEach(([lang, lines], i, o) => {
                let percent = (lines / total).toLocaleString("en", {
                  maximumFractionDigits: 2,
                  style: "percent"
                });
                div.innerHTML += `${lang}(${percent})${i < o.length? ', ': '.'}`;
              });
            }
            // JSON http Request
          let request = new XMLHttpRequest();
          request.onload = languages;
          request.open('GET', 'https://api.github.com/repos/DubDJ/' + repo + '/languages', true);
          request.send();
        };
    
        repoLanguage('chat-with-alex', 'languages');
    &lt;div id="languages"&gt;&lt;/div&gt;

    【讨论】:

    • 我通常对 JavaScript 缺乏经验,但感谢您扩展了额外的信息。解决了我的问题。
    • 我试图扩展答案并添加一些文档链接。祝你学习JS好运! :)
    • 太好了,感谢您提供的扩展答案。我肯定会计划在未来研究 ES7。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-06
    • 1970-01-01
    相关资源
    最近更新 更多