我正在创建一个javascript图表,我已经成功完成了,但我很多都有重复。
以下是我正在检索数据的示例xml,以便在条形图上显示。
如何对从xml中检索到的重复值进行求和?
<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);
}
});
}
答案 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
匹配,则递增每个PRINTS
,COPIES
和SERIAL
属性。
通过使用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"));
})