如何对数组中的重复项进行求和

时间:2018-01-18 20:12:04

标签: javascript jquery json ajax

我正在创建一个图表,我已经成功完成了,但我很多都有重复。

以下是我正在检索数据的示例,以便在条形图上显示。

如何对从中检索到的重复值进行求和?

<counts>
    <serial>3123111</serial>
    <scans>3</scans>
    <prints>1</prints>
    <copies>0</copies>
</counts>
<counts>
    <serial>3123111</serial>
    <scans>0</scans>
    <prints>2</prints>
    <copies>0</copies>
</counts>
<counts>
    <serial>AHTSD111</serial>
    <scans>0</scans>
    <prints>1</prints>
    <copies>2</copies>
</counts>
<counts>
    <serial>AHTSD111</serial>
    <scans>0</scans>
    <prints>1</prints>
    <copies>2</copies>
</counts>

我用于条形图的预期结果:

<counts>
    <serial>3123111</serial>
    <scans>3</scans>
    <prints>3</prints>
    <copies>0</copies>
</counts>
<counts>
    <serial>AHTSD111</serial>
    <scans>0</scans>
    <prints>2</prints>
    <copies>4</copies>
</counts>

检索数据并将其推送到图表数据,我知道我必须做一个循环来对每个序列号的扫描,打印,副本的值求和,但我仍然不断获取重复值,我只是将代码保留了。 / p>

$。AJAX({                 网址:“http://localhost5/api/”,                 dataType:'xml',                 方法:“GET”,                 成功:功能(数据){

                var parser = new DOMParser();
                var xmlDoc = parser.parseFromString(data, "text/html");
                data = xmlDoc.getElementsByTagName("JobCounts");

                var items = [];

                var serial, prints, copies, scans;

                function getAsText(parent, name) {
                    return parent.getElementsByTagName(name)[0].textContent
                }

                function getAsInt(parent, name) {
                    return parseInt(getAsText(parent, name));
                }

                for (i = 0; i < data.length; i++) {
                    items.push({
                        serial: getAsText(data[i], "serial"),
                        prints: getAsInt(data[i], "prints"),
                        copies: getAsInt(data[i], "copies"),
                        scans: getAsInt(data[i], "scans")
                    });


                }

                items = items.reduce((a, c) => {

                    var same = a.find(v => v.serial == c.serial);
                    console.log(same);
                    if (same) {
                        same.prints += c.prints;
                        same.copies += c.copies;
                        same.scans += c.scans;
                    } else {
                        a.push(c);
                    }
                    return a;
                }, []);

//“https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.4.0/Chart.min.js” //我正在使用的JS图表库

                var chartdata = {
                    labels: serial,
                    title: "Date",

                    datasets: [
                        {
                            label: 'Copies',
                            backgroundColor: 'rgba(0,255,0,0.6)',
                            data: copies
                       }
                    ]

                };
                var ctx = $("#mycanvas");

                var options = {
                    responsive: true,
                    title: {
                        display: true,
                        position: "top",
                        text: "DashBoard",
                        fontSize: 12,
                        fontColor: "#111"
                    },
                    legend: {
                        display: true,
                        position: "bottom",
                        labels: {
                           fontSize: 9
                        }
                    },
                    scales: {
                        yAxes: [{
                                ticks: {
                                    beginAtZero: true

                            }
                        }]
                    }
                };
                var barGraph = new Chart(ctx, {
                    'type': 'bar',
                    data: chartdata,
                    options : options,
                    "categoryField": "date",
                    "categoryAxis": {
                       "autoGridCount": false,
                       "gridCount": chartdata.length,
                        "gridPosition": "start",
                        "labelRotation": 90,
                        "startOnAxis": false,
                        "title":"Date"
                    }


                });
            },

            error: function (data) {
                console.log(data);
            }
        });
    }

2 个答案:

答案 0 :(得分:-1)

您可以将信息存储在单个对象数组中,而不是将信息存储在3个不同的数组中,这样可以更轻松地合并具有相同serial个数字的对象。

这就是我的意思:

var items = [];

function getAsText(parent, name){
    return parent.getElementsByTagName(name)[0].textContent
}

function getAsInt(parent, name){
    return parseInt(getAsText(parent, name));
}

for (i = 0; i < data.length; i++) {
   items.push({serial: getAsText(data[i], "serial"),
               prints: getAsInt(data[i], "prints"),
               copies: getAsInt(data[i], "copies"),
               scans: getAsInt(data[i], "scans")});
}


// Merge items with the same `serial` value;
items = items.reduce((a, c) => {
    var same = a.find(v => v.serial == c.serial);
    if(same){
       same.prints += c.prints;
       same.copies += c.copies;
       same.scans += c.scans;
    }else{
       a.push(c);
    }
    return a;
}, []);

答案 1 :(得分:-1)

您可以将每个counts元素.children.map()每个.tagName.textContent迭代到一个对象,将对象推送到一个数组,迭代数组如果SCANS匹配,则递增每个PRINTSCOPIESSERIAL属性。

通过使用JSON.forEach()迭代生成的数组,将Object.entries()转换为元素。

let data = `<counts>
<serial>3123111</serial>
<scans>3</scans>
<prints>1</prints>
<copies>0</copies>
</counts>

<counts>
<serial>3123111</serial>
<scans>0</scans>
<prints>2</prints>
<copies>0</copies>
</counts>

<counts>
<serial>AHTSD111</serial><scans>0</scans><prints>1</prints><copies>2</copies>
</counts>

<counts>
<serial>AHTSD111</serial><scans>0</scans><prints>1</prints><copies>2</copies>
</counts>`;

let parser = new DOMParser();
let xmlDoc = parser.parseFromString(data, "text/html");
let res = [];

for (let {counts:{SERIAL, SCANS, COPIES, PRINTS}} of 
    [...xmlDoc.querySelectorAll("counts")]
    .map(el =>
      ({counts:[...el.children]
               .reduce((o, {tagName, textContent}) =>
                 Object.assign(o, {[tagName]:textContent}), {})
       }))) {
  let curr = res.find(({counts:{SERIAL:s}}) => s === SERIAL); 
  if (!curr) {
    res.push({counts:{SERIAL, SCANS, COPIES, PRINTS}})
  } else {
    curr = curr.counts;
    curr.SCANS = +curr.SCANS + +SCANS;
    curr.PRINTS = +curr.PRINTS + +PRINTS;
    curr.COPIES = +curr.COPIES + +COPIES;
  }
}

res.forEach(o => {
  let key = Object.keys(o).pop();
  let parentNode = document.createElement(key);
  Object.entries(o[key])
  .forEach(([tagName, textContent]) => {
    let childNode = document.createElement(tagName)
    childNode.textContent = textContent;
    parentNode.appendChild(childNode);
    parentNode.appendChild(document.createElement("br"));
    document.body.appendChild(parentNode);
  })
  document.body.appendChild(document.createElement("br"));
})