Объединение одинаковых значений в столбцах таблицы
Здравствуйте, форумчане!
Есть массив вида {id:'1',name:'1',fid:''},{id:'2',name:'2',fid:'1'} ,{id:'3',name:'3',fid:''},{id:'4',name:'4',fid:'1' },{id:'5',name:'5',fid:'3'},{id:'6',name:'6',fid:' 3'}, и т.д.. Мне необходимо объединить ячейки в столбцах с одинаковыми fid. Нашел https://javascript.ru/forum/dom-wind...bedinenie.html, но здесь объединение строк. <script> window.addEventListener("DOMContentLoaded", function() { var a = document.querySelectorAll("tr"); [].forEach.call(a, function(c) { var a = c.querySelectorAll("td"); [].reduce.call(a, function(a, b) { if (b.textContent != a.textContent) return b; a.colSpan++; c.removeChild(b); return a }) }) }); </script> Поскольку я очень плохо разбираюсь в JS, простая замена в этом коде colSpan на rowSpan успеха не принесла даже если я вместо массива использую таблицу. |
Не совсем понятно
Цитата:
|
Вложений: 1
Прикрепил приблизительный файл.
Но изначально количество строк и количество одинаковых fid не известно, т.к. все зависит от выбора пользователя. |
Причем тут рисунок?
Вы пишете, что у вас есть массив {id:'1',name:'1',fid:''},{id:'2',name:'2',fid:'1'} ,{id:'3',name:'3',fid:''},{id:'4',name:'4',fid:'1' },{id:'5',name:'5',fid:'3'},{id:'6',name:'6',fid:' 3'}, и т.д.. Его надо во что то преобразовать. Что то с чем то объединить (с одинаковыми fid.) Вот есть {id:'1',name:'1',fid:''} и {id:'3',name:'3',fid:''}. Как их объединить? Что должно получиться в результате их объединения? |
Извините, что плохо объясняю, думал картинка будет понятней.
Может так будет понятней: ячейки в столбце fid с одинаковыми значениями объединить, если fid:'', их не объединять т.е. объединить ячейки из массива {id:'1',name:'1',fid:''},{id:'2',name:'2',fid:'1'} ,{id:'3',name:'3',fid:''},{id:'4',name:'4',fid:'1' },{id:'5',name:'5',fid:'3'},{id:'6',name:'6',fid:' 3'}, и т.д.. где fid:'1' и fid:'3' |
Может что-то типа этого нужно (как еще можно "объединить" такие данные я не представляю)?
function groupBy(iterable, key) { const result = {}; for (let item of iterable) { const itemKey = item[key] ?? ''; result[itemKey] ??= []; result[itemKey].push(item); } return result; } var data = [{id:'1',name:'1',fid:''},{id:'2',name:'2',fid:'1'} ,{id:'3',name:'3',fid:''},{id:'4',name:'4',fid:'1' },{id:'5',name:'5',fid:'3'},{id:'6',name:'6',fid:' 3'}]; console.log(groupBy(data, 'fid'));//{"1":[{"id":"2","name":"2","fid":"1"},{"id":"4","name":"4","fid":"1"}],"3":[{"id":"5","name":"5","fid":"3"}],"":[{"id":"1","name":"1","fid":""},{"id":"3","name":"3","fid":""}]," 3":[{"id":"6","name":"6","fid":" 3"}]} |
Может быть так будет понятней?
Мне бы таблицу получить из массива с объединением строк. <table> <tbody> <tr> <td>2</td> <td>2</td> <td rowspan="2">1</td> </tr> <tr> <td>4</td> <td>4</td> </tr> <tr> <td>9</td> <td>9</td> <td>9</td> </tr> <tr> <td>5</td> <td>5</td> <td rowspan="3">3</td> </tr> <tr> <td>6</td> <td>6</td> </tr> <tr> <td>8</td> <td>8</td> </tr> <tr> <td>10</td> <td>10</td> <td>10</td> </tr> </tbody> </table> |
Так?
<div id="table-container"></div> <style> table, th, td { border: 1px solid; border-collapse: collapse; } </style> <script> function groupBy(iterable, key) { const result = {}; for (let item of iterable) { const itemKey = item[key] ?? ''; result[itemKey] ??= []; result[itemKey].push(item); } return result; } function makeTableNode(groupedData, groupedByKey) { const values = Object.values(groupedData); const firstItem = values?.at(0)?.at(0); const table = document.createElement('table'); if (!firstItem) { return table; } // thead const thead = document.createElement('thead'); table.appendChild(thead); const tr = document.createElement('tr'); thead.appendChild(tr); for (let key in firstItem) { const th = document.createElement('th'); th.textContent = key; tr.appendChild(th); } // tbody const tbody = document.createElement('tbody'); table.appendChild(tbody); values?.forEach(list => { list.forEach((item, index)=> { const tr = document.createElement('tr'); tbody.appendChild(tr); for(let key in item) { const isGroupByKey = key === groupedByKey; if (index && isGroupByKey) { continue; } const td = document.createElement('td'); tr.appendChild(td); td.textContent = item[key]; if (isGroupByKey && list.length) { td.rowSpan = list.length; } } }); }); return table; } var data = [{id:'1',name:'1',fid:''},{id:'2',name:'2',fid:'1'} ,{id:'3',name:'3',fid:''},{id:'4',name:'4',fid:'1' },{id:'5',name:'5',fid:'3'},{id:'6',name:'6',fid:' 3'}]; (data => { const container = document.querySelector('#table-container'); if (!container) { return; } container.innerHTML = ''; container.appendChild( makeTableNode( groupBy(data, 'fid'), 'fid' ) ); })(data); </script> |
Вопросы.
У вас в примере есть строки с fid:''. На рисунке строки с пустым fid не объединены. Что на самом деле надо делать с такими строками? Могут ли строки с одинаковым fid идти не подряд? ({id:'2',name:'2',fid:'1'} ,{id:'3',name:'3',fid:''},{id:'4',name:'4',fid:'1' }) Что делать в этом случае? Строки с одинаковым fid переставлять так, что бы они шли подряд? Что является входом? Некоторый массив или есть исходная таблица, которую надо реорганизовать? |
Цитата:
Да, строки с одинаковыми fid могут идти не друг за другом и их необходимо будет переставить. Есть только массив, в котором количество строк изначально неизвестно и количество одинаковых fid также неизвестно, может быть 0, а может быть и 10. |
Цитата:
Только с пустыми fid не объединять, а строки с fid:'3' - объединить. |
<head> <style> table { border: 1px solid black; border-collapse: collapse; } td { border: 1px solid black; } </style> </head> <body> <table id="mytable"></table> <script> const data = [ {id:"1", name: "1", fid:""}, {id:"2", name: "2", fid:"1"}, {id:"3", name: "3", fid:"3"}, {id:"4", name: "4", fid:"4"}, {id:"5", name: "5", fid:"1"}, {id:"6", name: "6", fid:""}, {id:"7", name: "7", fid:"5"}, {id:"8", name: "8", fid:""}, {id:"9", name: "9", fid:"3"}, {id:"10", name: "10", fid:"1"}, {id:"11", name: "11", fid:""}, {id:"12", name: "12", fid:"5"} ]; function groupe (data) { const groupedata = []; for (const {id, name, fid} of data) { if (fid === "") { groupedata.push({rows:[{id, name}], fid}); } else { const row = groupedata.find(row => row.fid === fid) if (!row) { groupedata.push({rows:[{id, name}], fid}); } else { row.rows.push({id, name}) } } } return groupedata; } function createtable (table, groupedata) { const thead = document.createElement('thead') thead.innerHTML = '<tr><th>id</th><th>name</th><th>fid</th></tr>'; table.append(thead); const tbody = document.createElement('tbody'); for (const {rows, fid} of groupedata) { for (let i = 0; i<rows.length; i++) { const row = document.createElement('tr'); const tdid = document.createElement('td'); const tdname = document.createElement('td'); tdid.textContent = rows[i].id; tdname.textContent = rows[i].name; row.append(tdid,tdname); if (i === 0) { const tdfid = document.createElement('td'); tdfid.textContent = fid; tdfid.rowSpan = rows.length; row.append (tdfid) } tbody.append (row); } } table.append(tbody); } const groupedata = groupe(data); createtable(document.getElementById('mytable'), groupedata); </script> <body> |
Цитата:
Плюсик поставил, жаль что нельзя поставить 5. А можно еще попросить проставить комментарии в какой строке что происходит. Мне хотелось бы не просто скопипастить код, но и самому понять где, что и как, т.к. я хочу научиться сам это делать. |
Цитата:
|
Цитата:
К тому же завтра выходные, заниматься изучением будет некогда. И еще вопрос: Я немного изменил массив, оставил только fid:"1" для удобства const data = [ {id:"2", name: "2", fid:"1"}, {id:"6", name: "2", fid:"1"}, {id:"2", name: "2", fid:"1"}, {id:"7", name: "7", fid:"1"}, {id:"10", name: "10", fid:"1"}, ]; столбец fid:"1" получается объединенный, как продолжить объединение ячеек в других столбцах, например где name: "2" и id:"2" ? соответственно, так же изначально неизвестно количество name: "2" и id:"2" Если "криво" объяснил, пишите. |
Anat37, если у вас id где-то повторяется, то у вас что-то не так с данными, потому что id предполагается уникальным.
|
Цитата:
|
Почему сразу не спросить все то, что нужно.
А то - сначала "для разминки" скажите как сделать то, потом усложним задание, сделайте это. Спросите сразу все, что надо. Сделайте нормальный тестовый пример, что бы нам его не придумывать... |
Цитата:
1. Извините что сразу не ответил, в выходные занят сильно. 2. Нивкоем разе не хотел никого обидеть, я самостоятельно пытаюсь изучить JS и сам себе придумываю задания. Поэтому так и получилось.Извините еще раз. Попробую объяснить задачу: В таблице количество столбцов изначально неизвестно (может быть 1, а может быть и 10). В каждом столбце могут быть одинаковые строки. Сначала идет объединение по первому столбцу, потом по второму, но объединяются строки, которые входят в объединенные строки первого столбца и т.д.. const data = [ {id:"2", name: "2", fid:"1"}, {id:"6", name: "2", fid:"1"}, {id:"2", name: "2", fid:"1"}, {id:"7", name: "7", fid:"1"}, {id:"10", name: "10", fid:"1"}, {id:"11", name: "11", fid:"2"}, {id:"12", name: "11", fid:"2"}, {id:"1", name: "1", fid:"2"}, {id:"10", name: "10", fid:"2"}, {id:"5", name: "5", fid:""}, {id:"3", name: "5", fid:""}, ]; т.е. из этого объединение нет по строке вообще если первый столбец пустой, {id:"10", name: "10", fid:"1"}, и {id:"10", name: "10", fid:"2"}, объединения по id и name нет, т.к. они в разных объединения первого столбца. Надеюсь объяснил правильно. И еще вопрос: можете посоветовать учебное пособие для самостоятельного изучения? Здесь вот есть похожее, но из таблицы, а не из массива: https://stackoverflow.com/questions/...ing-javascript |
Цитата:
Цитата:
Цитата:
|
Цитата:
2. Спасибо, сейчас перейду. 3. Тогда можно ограничить до 8 столбцов. |
Цитата:
|
Цитата:
const data = [ {id:"2", name: "2", fid:"1"}, {id:"6", name: "2", fid:"1"}, {id:"2", name: "2", fid:"1"}, {id:"7", name: "7", fid:"1"}, {id:"10", name: "10", fid:"1"}, {id:"11", name: "11", fid:"2"}, {id:"12", name: "11", fid:"2"}, {id:"1", name: "1", fid:"2"}, {id:"10", name: "10", fid:"2"}, {id:"5", name: "5", fid:""}, {id:"3", name: "5", fid:""}, ]; Мне бы только понять сам принцип. |
Цитата:
У вас уже есть 2 примера готовых скриптов для разбора, изучайте оба и пробуйте написать то, что вам нужно. По ходу дела, если необходимо, задавайте вопросы. |
Цитата:
container.innerHTML = ''; container.appendChild( makeTableNode( groupBy(data, 'fid'), 'fid' ) чтобы объединились 'name' в уже объединенных 'fid'? |
Цитата:
Объединение происходит в функции groupBy. |
Цитата:
groupBy(data, ['fid'], ['name']) не работает |
Anat37, начните с изучения основ js. Узнайте как работают функции, какие типы данных бывают и т.п.
От того, что вы в функцию, которая принимает 2 аргумента и вторым должна быть строка передадите 3 аргумента, где последние два - массивы, ничего не изменится. Программирование так не работает, это не волшебство. |
Часовой пояс GMT +3, время: 11:58. |