2016-09-14 10 views
0

Мне поручено создать таблицу временных таблиц, в которой будут отображаться часы, отработанные каждым клиентом в день. Таблица должна выглядеть как на картинке ниже фрагменте кода:Группировка и суммирование массива объектов Javascript

table, td, th { 
 
      border: 1px solid black; 
 
     }
<div> 
 
    <table id="testTable" class="table"> 
 
    <tr> 
 
     <th>Client name</th> 
 
     <th>Monday</th> 
 
     <th>Tuesday</th> 
 
     <th>Wednesday</th> 
 
     <th>Thursday</th> 
 
     <th>Friday</th> 
 
     <th>Saturday</th> 
 
     <th>Sunday</th> 
 
    </tr> 
 
    <tr> 
 
     <td>client1</td> 
 
     <td>0</td> 
 
     <td>5</td> 
 
     <td>3</td> 
 
     <td>2</td> 
 
     <td>3</td> 
 
     <td>0</td> 
 
     <td>0</td> 
 
    </tr> 
 
    <tr> 
 
     <td>client2</td> 
 
     <td>4</td> 
 
     <td>1</td> 
 
     <td>4</td> 
 
     <td>2</td> 
 
     <td>1</td> 
 
     <td>0</td> 
 
     <td>0</td> 
 
    </tr> 
 
    </table> 
 
</div>
проблема, которую я имею, что после запроса элементы расписаний, необходимые для заполнения таблицы, я не уверен, как группировать каждый элемент по имени клиента и день недели. Массив извлекаться будет выглядеть примерно так:

timesheetItems = [ 
 
    timesheetItem = { 
 
     clientName: client1, 
 
     hoursWorked: 2, 
 
     day: Monday 
 
    }, 
 
    timesheetItem = { 
 
     clientName: client1, 
 
     hoursWorked: 3, 
 
     day: Monday 
 
    }, 
 
    timesheetItem = { 
 
     clientName: client1, 
 
     hoursWorked: 4, 
 
     day: Wednesday 
 
    }, 
 
    timesheetItem = { 
 
     clientName: client2, 
 
     hoursWorked: 4, 
 
     day: Monday 
 
    } 
 
    
 
    ];
сгруппированных массив должен сгруппировать все элементы Timesheet в один объект на одного клиента и имеют ключи для каждого дня недели, который содержит сумму отработанных часов для тот день. Окончательный массив должен выглядеть примерно так:

groupedArray = { 
 
    Client1 = { 
 
    Mon: 5, 
 
    tues: 3, 
 
    ... 
 
    sun: 0 
 
    }, 
 
    client2 = { 
 
    mon:2, 
 
    ... 
 
    }, 
 
    client3 = { 
 
    ... 
 
    }, 
 
    ... 
 
}

Так что, если кто-нибудь может подсказать, как идти о группировке массив Timesheet пунктов, так что результат будет выглядеть выше фрагмент кода, так что я могу легко петля из сгруппированного массива, чтобы заполнить таблицу, было бы очень полезно. Спасибо.

+0

[Массив # уменьшить] (https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce) – Xotic750

ответ

1

Чтобы агрегировать массив, который вы можете использовать reduce:

const groupedArray = timesheetItems.reduce((prev, curr) => { 
    if (!prev[curr.clientName]) { 
     prev[curr.clientName] = {}; 
    } 
    if (!prev[curr.clientName][curr.day]) { 
     prev[curr.clientName][curr.day] = 0 
    } 
    prev[curr.clientName][curr.day] += curr.hoursWorked; 
    return prev; 
}, {}); 
0

Вы можете использовать Array#forEach и проверить существующие объекты. Если не существует, назначьте новый объект или значение.

var timesheetItems = [{ clientName: 'client1', hoursWorked: 2, day: 'Monday' }, { clientName: 'client1', hoursWorked: 3, day: 'Monday' }, { clientName: 'client1', hoursWorked: 4, day: 'Wednesday' }, { clientName: 'client2', hoursWorked: 4, day: 'Monday' }], 
 
    grouped = {}; 
 

 
timesheetItems.forEach(a => { 
 
    grouped[a.clientName] = grouped[a.clientName] || {}; 
 
    grouped[a.clientName][a.day] = (grouped[a.clientName][a.day] || 0) + a.hoursWorked; 
 
}); 
 

 
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }

0

Мы могли бы использовать tableMaker() функции для создания таблицы из массива объектов, где каждый объект назначает строку таблицы, свойство объектов обозначают заголовки и значение данных клетки. Но сначала мы должны преобразовать наши данные в форму, которую может понять функция tableMaker(). Такие, как

[ { 'Client Name': 'client1', 
    Monday: 5, 
    Tuesday: 0, 
    Wednesday: 4, 
    Thursday: 0, 
    Friday: 0 }, 
    { 'Client Name': 'client2', 
    Monday: 4, 
    Tuesday: 0, 
    Wednesday: 0, 
    Thursday: 0, 
    Friday: 0 } ] 

Так вот код для таблицы.

function tableMaker(o,h=true){ 
 
    var keys = Object.keys(o[0]), 
 
    rowMaker = (a,t) => a.reduce((p,c,i,a) => p + (i === a.length-1 ? "<" + t + ">" + c + "</" + t + "></tr>" 
 
                    : "<" + t + ">" + c + "</" + t + ">"),"<tr>"), 
 
     rows = o.reduce((r,c) => r + rowMaker(keys.reduce((v,k) => v.concat(c[k]),[]),"td"),h ? rowMaker(keys,"th") : []); 
 
    return "<table>" + rows + "</table>"; 
 
} 
 

 
function giveMeNewClient(o){ 
 
    var templateObject = { 
 
    \t     "Client Name": "", 
 
    \t      "Monday": 0, 
 
    \t      "Tuesday": 0, 
 
    \t     "Wednesday": 0, 
 
    \t     "Thursday": 0, 
 
    \t      "Friday": 0 
 
         }; 
 
    return Object.assign(templateObject,o); 
 
} 
 
var timesheetItems = [{ 
 
         clientName: "client1", 
 
         hoursWorked: 2, 
 
           day: "Monday" 
 
         }, 
 
         { 
 
         \t clientName: "client1", 
 
         hoursWorked: 3, 
 
           day: "Monday" 
 
         }, 
 
         { 
 
         \t clientName: "client1", 
 
         hoursWorked: 4, 
 
           day: "Wednesday" 
 
         }, 
 
         { 
 
         \t clientName: "client2", 
 
         hoursWorked: 4, 
 
           day: "Monday" 
 
         } 
 
        ], 
 

 
     tableData = timesheetItems.reduce((res,c) => { var client = res.find(o => o["Client Name"] === c.clientName); 
 
                 client ? client[c.day]+= c.hoursWorked 
 
                   : res.push(giveMeNewClient({"Client Name": c.clientName, [c.day]: c.hoursWorked})); 
 
                 return res; 
 
                 },[]), 
 
     tableHTML = tableMaker(tableData); 
 
myTable.innerHTML = tableHTML;
<div id="myTable"></div>

Смежные вопросы