#javascript #jquery
#javascript #jquery
Вопрос:
Есть два запроса / URL API
Это первый URL-адрес запроса API и данные, поступающие из
http://127.0.0.1:8000/api/onlineUserData
{"onlineUserData":[
["Month" , "Amania" , "Shyral" , "Dorpan"],
["Nov-16" , 9 , 11 , 6 ] ,
["Nov-18" , 5 , 0 , 0 ]
]};
Это второй URL-адрес запроса API и данные, поступающие из
http://127.0.0.1:8000/api/offlineUserData
{"offlineUserData":[
["Month" , "Amania" , "Shyral" , "Diskhant"],
["Nov-16" , 4 , 7 , 0 ],
["Nov-20" , 12 , 8 , 9 ],
]};
Теперь я хочу суммировать два JSON-данных, если их имя пользователя и месяц / дата совпадают между двумя данными API
{"AllUser":[
[" Month" , "Amania" , "Shyral" , "Dorpan","Diskhant" ],
[" Nov-16" , 13 , 18 , 6 , 0 ],
[" Nov-18 " , 5 , 0 , 0 , 0 ],
[" Nov-20 " , 12 , 8 , 0 , 9 ], ]
]
Комментарии:
1. Привет, Саурав, и добро пожаловать в SO. Есть ли особая причина, по которой ваши данные структурированы как вложенный массив? И если нет, можете ли вы преобразовать свои данные в объектную форму, например:
[{ date: '2019-11-16', "Amania": 9, "Shyral": 11, "Dorphan": 6 }, { ... }]
. Это значительно упростит объединение, добавление и различие и сделает ваши данные более значимыми.2. Данные @EmielZuurbier отправляются таким образом, хотя служат. Они отправили этот формат JSON для использования в диаграмме Google. Мне просто нужно суммировать два JSON-данных.Так
Ответ №1:
Самым большим препятствием при объединении этих двух наборов является то, что значения помещаются внутри вложенных массивов. Это означает, что позиция, в которой они находятся, является единственным показателем того, что означает значение.
Для этого данные необходимо преобразовать в структуру с ключами и значениями. Это дает каждому значению имя и значение того, что это такое, а также делает их объединение менее подверженным ошибкам.
[
{
'Month': 'Nov-16',
'Amania': 9,
'Shyral': 11,
'Dorpan': 6
},
{
...
},
...
];
Теперь вам нужно убедиться, что все ваши ключи совпадают, чтобы при начале подсчета у вас были равные наборы данных для подсчета.
Обратите внимание, что это Diskhant
было добавлено к объекту ниже. Теперь это имя существует в каждом объекте, и можно вычислить общее его количество.
[
{
'Month': 'Nov-16',
'Amania': 9,
'Shyral': 11,
'Dorpan': 6,
'Diskhant': 0
},
{
...
},
...
];
Отсюда вы можете объединить два набора в один и начать фильтрацию повторяющихся Month
значений. При возникновении такого дублирования добавьте значение текущего объекта и верните результат.
Я действительно считаю, что это можно упростить, но моя попытка заставила меня выполнить все эти вспомогательные функции, чтобы убедиться, что данные обрабатываются правильно. Это также позволяет вам вводить более 2 наборов данных, если вам нужно их объединить.
const online = {
"onlineUserData": [
["Month", "Amania", "Shyral", "Dorpan"],
["Nov-16", 9, 11, 6],
["Nov-18", 5, 0, 0]
]
};
const offline = {
"offlineUserData": [
["Month", "Amania", "Shyral", "Diskhant"],
["Nov-16", 4, 7, 0],
["Nov-20", 12, 8, 9],
]
};
/**
* Converts the nested arrays to an array of objects.
*/
const tableToObjects = data => {
const [ headers, ...entries ] = data;
return entries.map(entry => entry.reduce((acc, cur, i) => {
acc[headers[i]] = cur;
return acc;
}, {}));
};
/**
* Converts an array of objects into nested arrays.
*/
const objectsToTable = data => [
Object.keys(data[0]),
...(data.map(entry => Object.values(entry)))
];
/**
* Returns an array of all keys that are present.
*/
const getKeyMap = data => [...data.reduce((set, entry) => {
Object.keys(entry).forEach(key => set.add(key));
return set;
}, new Set())];
/**
* Modifies the data to ensure that all objects have the
* same keys. This is necessary to get a correct output
* when counting and adding up the values of each object.
*/
const equalizeData = data => {
const keys = getKeyMap(data);
return data.map(entry => keys.reduce((obj, key) => {
obj[key] = entry[key] || 0
return obj;
}, {}));
}
/**
* Merges the data by the Month property.
* If a Month is already present in the array then the values
* of that object will be added to the existing object.
*/
const mergeData = data => data.reduce((arr, entry) => {
const { Month, ...rest } = entry;
const present = arr.find(newEntry => newEntry['Month'] === Month);
if (present) {
Object.entries(rest).forEach(([ key, value ]) => {
present[key] = (present[key] || 0) value;
});
} else {
arr.push(entry);
}
return arr;
}, []);
/**
* Function that uses all the functions from above to combine
* the two nested arrays into a single nested array.
* Returns an object with a single `allUsers` property.
*/
const allUsers = (...dataSets) => {
const allData = dataSets.flatMap(dataSet => {
const table = Object.values(dataSet)[0];
return tableToObjects(table);
});
const equalizedData = equalizeData(allData)
const mergedData = mergeData(equalizedData);
return {
'allUsers': objectsToTable(mergedData)
};
};
// Call the function.
const result = allUsers(online, offline);
// This is just to see the output of the function.
const output = document.getElementById('output');
output.innerHTML = JSON.stringify(result, null, 2);
pre {
display: inline-block;
background-color: #f7f7f7;
border: 1px solid #d0d0d0;
border-radius: 5px;
padding: 15px;
}
<code><pre id="output"></pre></code>
Комментарии:
1. привет, спасибо за ваш ответ. я просто попробую ваше решение и дам вам ответ