Я пытаюсь подвести итоги col1, col2 и col3 в моем JSON с использованием JQuery и не знаю, как это сделать, используя цикл.each. Другая проблема - col1, col2 и col3 - динамические, поэтому имена будут меняться.
Это моя строка JSON:
var data = [
{
"Country": "Spain",
"Year": "2012",
"col1": "100.75",
"col2": "500",
"col3": "200"
},
{
"Country": "Spain",
"Year": "2013",
"col1": "200",
"col2": "500",
"col3": "300"
},
{
"Country": "France",
"Year": "2011",
"col1": "100",
"col2": "100",
"col3": "300"
},
{
"Country": "France",
"Year": "2012",
"col1": "100",
"col2": "100",
"col3": "300"
},
{
"Country": "France",
"Year": "2013",
"col1": "100",
"col2": "200",
"col3": "300"
}
]
Я хочу два результата, которые будут выглядеть примерно так:
1) Итого по стране
Spain 300.75, 1000, 500
France 300, 400, 900
2) Всего:
["col1", 600.75],
["col2", 1400],
["col3", 1400]
Спасибо, спасибо!
Для хранения результатов лучше использовать объект (или ассоциативный массив). Также не следует смешивать свойства, которые следует применять, а это не должно - вы можете хранить их в отдельном массиве, который может быть свойством в файле конфигурации или smth. Вот код (jsFiddle):
var countries = {},
columns = {},
sumCols = ['col1', 'col2', 'col3'];
$.each(data, function(index, obj) {
if (!countries[obj['Country']]) {
countries[obj['Country']] = {};
}
$.each(sumCols, function (index, col) {
if (!countries[obj['Country']][col]) {
countries[obj['Country']][col] = 0;
}
if (!columns[col]) {
columns[col] = 0;
}
var val = parseFloat(obj[col]);
if (!isNaN(val)) {
countries[obj['Country']][col] += val;
columns[col] += val;
}
});
});
В результате:
{
"Spain":{
"col1":300.75,
"col2":1000,
"col3":500},
"France":{
"col1":300,
"col2":400,
"col3":900
}
}
{
"col1":600.75,
"col2":1400,
"col3":1400
}
Основной проблемой, с которой вам придется столкнуться с динамическими именами свойств, является тот факт, что JavaScript явно не гарантирует упорядочение. Таким образом, вы не можете сопоставить цикл с именами объектов объектов с индексом массива. Из-за этого вам нужно будет использовать объекты для хранения ваших результатов. Здесь (не очень оптимизированный) бит кода, который должен работать. После этого вы можете манипулировать результатами.
var results = {};
var totals = {};
// Loop over the array of data
for (var d = 0; d < data.length; d++) {
var o = data[d];
var country = o["Country"];
var values = results[country] || {};
// Since the column names may change, we need to loop over the object
for (var key in o) {
// Weed out the two known keys
if (o.hasOwnProperty(key) && key.toLowerCase() != "country" && key.toLowerCase() != "year") {
// Now find the entry in the values obj that matches
var column = values[key] || 0;
// And the corresponding entry in the totals object
var totalsColumn = totals[key] || 0;
column += parseFloat(o[key]);
totalsColumn += parseFloat(o[key]);
values[key] = column;
totals[key] = totalsColumn;
}
}
results[country] = values;
}
Это дает два объекта, results
, которые выглядят следующим образом:
France:
col1: 300
col2: 400
col3: 900
Spain:
col1: 300.75
col2: 1000
col3: 500
И totals
, которые выглядят следующим образом:
col1: 600.75
col2: 1400
col3: 1400
Я разместил это в обновленной версии вашей скрипки.