Как найти сумму объектов в массиве на javascript
Мне задали тестовое задание где нужно сделать интерактивную таблицу на js с подстановкой данных из массива.
https://i.stack.imgur.com/EnA47.png
В общем я встал на том моменте посчитать сумму значений ключа real_time у определенного и добавить это все в столб отработанное время. Нашел сумму с помощью reduce, но не могу понять как мне подставить это значение в таблицу. Уж очень хочется сделать это задание.Дайте хотя бы подсказку как решить
const table = document.querySelector('.table');
const tbody = document.querySelector('.tbody');
const users = [{
id: 1,
name: 'Павел',
login: 'Pavel',
role: 'менеджер',
action: '',
},
{
id: 2,
name: 'Егор',
login: 'Pavel',
role: 'менеджер',
action: '',
},
{
id: 3,
name: 'Дмитрий',
login: 'Pavel',
role: 'менеджер',
action: '',
},
];
const data = [{
id: 1,
id_user: 1,
task: "корректировка",
execution_time: 2,
real_time: 3,
date: '21 jun 2021 year'
},
{
id: 2,
id_user: 2,
task: "корректировка",
execution_time: 2,
real_time: 3,
date: '21 jun 2021 year'
},
{
id: 3,
id_user: 3,
task: "корректировка",
execution_time: 2,
real_time: 3,
date: '21 jun 2021 year'
},
];
//здесь нахожу сумму отработанного времени у определенного пользователя
const summed = data.reduce((acc, record) => {
const {
id_user,
real_time
} = record;
if (!acc[id_user]) acc[id_user] = {
real_time: 0
};
acc[id_user].real_time += real_time;
return acc;
}, []);
console.log(summed);
//Здесь добавляю name из массива users
const usermap = {};
users.forEach(function(user) {
usermap[user.id] = user;
});
data.forEach(function(item) {
item.user = usermap[item.id_user];
});
//создаю таблицу со значениями
const renderTable = () => {
for (let user of data) {
let tr = document.createElement('tr');
let td1 = document.createElement('td');
td1.innerHTML = user.id_user;
tr.appendChild(td1);
let td2 = document.createElement('td');
td2.innerHTML = user.user.name;
tr.appendChild(td2);
let td3 = document.createElement('td');
td3.innerHTML = user.real_time;
tr.appendChild(td3);
let td4 = document.createElement('td');
td4.innerHTML = user.execution_time;
tr.appendChild(td4);
tbody.appendChild(tr);
}
}
renderTable();
<!doctype html>
<html lang="ru">
<head>
<!-- Обязательные метатеги -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-+0n0xVW2eSR5OomGNYDnhzAbDsOXxcvSN1TPprVMTNDbiYZCxYbOOl7+AMvyTG2x" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css">
<link rel="stylesheet" href="./blocks/index.css">
<title>Привет мир!</title>
</head>
<body>
<table class="table">
<thead>
<tr>
<th scope="col">id</th>
<th scope="col">Пользователь</th>
<th scope="col">Отработанное время</th>
<th scope="col">Переработка</th>
</tr>
</thead>
<tbody class="tbody">
</tbody>
</table>
<script src="index.js"></script>
</body>
Ответы (1 шт):
Решение из вопроса по-моему содержит смысловую ошибку, которую исправил в примере ниже. Ошибка заключается в том, что перебирается не тот массив.
Вывод таблицы пользователей предполагает цикл по массиву пользователей (users) - но код из вопроса почему-то перебирает массив данных (data).
Почему перебирать следует именно массив пользователей, а не массив данных?
Давай на минутку забудем о том что просто естественно/логично, и внимательнее посмотрим на суть поставленной задачи: "суммировать время каждого пользователя из данных".
Задача практически говорит нам, что данные могут содержать несколько записей об одном пользователе. Иначе, если в данных всегда будет лишь одна запись на каждого пользователя - то и суммировать будет нечего, правильно? (задача в этом случае потеряет всякий смысл)
А теперь подумаем чуть дальше: что же случится когда будет несколько записей об одном юзере? Выводя табличку из массива данных, мы получим дублирование пользователей в таблице. Выводить одни и те же имена несколько раз, с разными показателями времени - это очень странно!.. и явно не то что нужно.
Соответственно, пересмотрим код:
- исправляем итерируемый массив в for-цикле построения таблички
- учитывая то что теперь перебор массива пользователей, нам становится совсем не нужно перед этим перебором линковать объект каждого пользователя в каждый объект массива данных (удаляем эту часть кода);
- если мы выводим результат по пользователям, и считаем сумму
real_time, то и второе времяexecution_timeнаверное тоже надо суммировать (добавляем подсчет в функцию-редьюсер) - хорошо бы видеть, работает ли вообще наше суммирование, а значит нам надо добавить еще как минимум одно слагаемое (в массив данных добавляем еще объектов с показателями времени - в примере я добавил только один объект данных, для пользователя с
id: 2)
Результат:
const table = document.querySelector('.table'),
tbody = table.tBodies[0];
const users = [
{ id: 1, name: 'Павел', login: 'Pavel', role: 'менеджер', action: '' },
{ id: 2, name: 'Егор', login: 'Pavel', role: 'менеджер', action: '' },
{ id: 3, name: 'Дмитрий', login: 'Pavel', role: 'менеджер', action: '' },
];
const data = [
{ id: 1,
id_user: 1,
task: "корректировка",
execution_time: 2,
real_time: 3,
date: '21 jun 2021 year'
},
{
id: 2,
id_user: 2,
task: "корректировка",
execution_time: 2,
real_time: 3,
date: '21 jun 2021 year'
},
{
id: 3,
id_user: 3,
task: "корректировка",
execution_time: 2,
real_time: 3,
date: '21 jun 2021 year'
},
{
id: 4,
id_user: 2,
task: "корректировка",
execution_time: 2,
real_time: 5,
date: '21 jun 2021 year'
},
];
//здесь нахожу сумму отработанного времени у определенного пользователя
const summed = data.reduce((acc, { id_user, real_time, execution_time }) => {
let user = acc[id_user];
if (!user)
user = acc[id_user] = { real_time: 0, execution_time: 0 };
user.real_time += real_time;
user.execution_time += execution_time;
return acc;
}, {});
// console.log(summed);
//Здесь добавляю name из массива users
const usermap = {};
users.forEach(function(user) {
usermap[user.id] = user;
});
//создаю таблицу со значениями
const renderTable = () => {
for (const user of users) {
const tr = tbody.insertRow();
tr.insertCell().textContent = user.id;
tr.insertCell().textContent = user.name;
tr.insertCell().textContent = summed[user.id].real_time;
tr.insertCell().textContent = summed[user.id].execution_time;
}
}
renderTable();
<!doctype html>
<html lang="ru">
<head>
<!-- Обязательные метатеги -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-+0n0xVW2eSR5OomGNYDnhzAbDsOXxcvSN1TPprVMTNDbiYZCxYbOOl7+AMvyTG2x" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css">
<link rel="stylesheet" href="./blocks/index.css">
<title>Привет мир!</title>
</head>
<body>
<table class="table">
<thead>
<tr>
<th scope="col">id</th>
<th scope="col">Пользователь</th>
<th scope="col">Отработанное время</th>
<th scope="col">Переработка</th>
</tr>
</thead>
<tbody class="tbody">
</tbody>
</table>
<script src="index.js"></script>
</body>