简体   繁体   English

如何使用 d3.js 按不同变量对表进行排序?

[英]How can I use d3.js to sort a table by different variables?

 data = [ { "name": "Dave", "dept": "Marketing", "region": "South", "items": 28 }, { "name": "Amy", "dept": "IT", "region": "West", "items": 46 }, { "name": "John", "dept": "Sales", "region": "North", "items": 35 }, { "name": "Sarah", "dept": "Communications", "region": "North", "items": 13 } ] drawTable(data) sortTable(data) function drawTable(data) { // not working // when redrawing table, trying to re-initialize sort function sortTable(data) d3.select('#data-table').remove() let table = d3.select('#table').append('div').attr('id', 'data-table') let row = table.selectAll('.row') .data(data) .enter() .append('div') .attr('class', 'row') let grid = row .append('div') .attr('class', 'grid') let name = grid.append('div') .attr('class', 'box') .html(d => d.name) let dept = grid.append('div') .attr('class', 'box') .html(d => d.dept) let region = grid.append('div') .attr('class', 'box') .html(d => d.region) let items = grid.append('div') .attr('class', 'box') .html(d => d.items) } function sortTable(data) { d3.selectAll(".name,.dept,.region,.items").on('click', function () { let sortWhich = d3.select(this).attr("class") console.log('sortWhich', sortWhich) let tableSort if (sortWhich == "name") { tableSort = data.sort((a, b) => d3.ascending(a.name, b.name)) } else if (sortWhich == "dept") { tableSort = data.sort((a, b) => d3.ascending(a.dept, b.dept)) } else if (sortWhich == 'region') { tableSort = data.sort((a, b) => d3.ascending(a.region, b.region)) } else { tableSort = data.sort((a, b) => d3.ascending(a.items, b.items)) } // Can I combine the above and pass a variable to a sort function? This is not working: // let tableSort = data.sort((a, b) => a.sortWhich - b.sortWhich) drawTable(tableSort) }) }
 html, body { height: 100%; margin: 0; } .grid { display: flex; flex-wrap: wrap; flex-direction: row; } .grid>div { display: flex; flex-basis: calc(100%/4 - 28px); justify-content: center; flex-direction: column; padding: 10px; } .box { margin: 0; } .box { color: #000; border: .5px solid #ccc; } .hrbox { background-color: #333; color: #fff; }
 <!DOCTYPE html> <html lang="en"> <head> <script src="https://d3js.org/d3.v6.min.js"></script> </head> <body> <div id="table"> <div class="grid"> <div class="box hrbox name"> <div>name</div> </div> <div class="box hrbox dept"> <div>dept</div> </div> <div class="box hrbox region"> <div>region</div> </div> <div class="box hrbox items"> <div>items</div> </div> </div> <div id="data-table"></div> </div> </body>

I created a flexbox table using d3.js that pulls json data to populate it.我使用 d3.js 创建了一个 flexbox 表,它拉取 json 数据来填充它。 I want to be able to sort each column by its header row, and I wrote a sort function for that.我希望能够按标题行对每一列进行排序,为此我编写了一个排序函数。 However, I'm only able to sort one column at a time right now.但是,我现在一次只能对一列进行排序。 Then if I refresh the page, I can sort a different column.然后,如果我刷新页面,就可以对不同的列进行排序。 I want to be able to switch without needing to refresh the page.我希望能够在不需要刷新页面的情况下进行切换。 So- sort by name, then decide to sort by items, then region, to see different views of the data.因此,按名称排序,然后决定按项目排序,然后按区域排序,以查看数据的不同视图。 What am I missing?我错过了什么?

I'd appreciate any feedback.我很感激任何反馈。

[I'd also like to just have one sort function that I pass a variable to instead of having all those conditionals. [我也希望只有一个排序函数,我将一个变量传递给它,而不是拥有所有这些条件。 I'm not sure if it's possible.我不确定这是否可能。 (Definitely not my main concern.) But putting it out there] (绝对不是我主要关心的问题。)但是把它放在那里]

Thanks!谢谢!

If you look at the console you'll see that sortWhich is always something like "box hrbox whatever" , and because of that all conditions will fail and the code will go to the else at the bottom.如果您查看控制台,您会看到sortWhich总是类似于"box hrbox whatever" ,因此所有条件都将失败,代码将转到底部的else

A simplest solution is using includes() :最简单的解决方案是使用includes()

if (sortWhich.includes("name")) etc...

Here is your code with that change:这是带有该更改的代码:

 data = [{ "name": "Dave", "dept": "Marketing", "region": "South", "items": 28 }, { "name": "Amy", "dept": "IT", "region": "West", "items": 46 }, { "name": "John", "dept": "Sales", "region": "North", "items": 35 }, { "name": "Sarah", "dept": "Communications", "region": "North", "items": 13 } ] drawTable(data) sortTable(data) function drawTable(data) { // not working // when redrawing table, trying to re-initialize sort function sortTable(data) d3.select('#data-table').remove() let table = d3.select('#table').append('div').attr('id', 'data-table') let row = table.selectAll('.row') .data(data) .enter() .append('div') .attr('class', 'row') let grid = row .append('div') .attr('class', 'grid') let name = grid.append('div') .attr('class', 'box') .html(d => d.name) let dept = grid.append('div') .attr('class', 'box') .html(d => d.dept) let region = grid.append('div') .attr('class', 'box') .html(d => d.region) let items = grid.append('div') .attr('class', 'box') .html(d => d.items) } function sortTable(data) { d3.selectAll(".name,.dept,.region,.items").on('click', function() { let sortWhich = d3.select(this).attr("class") console.log('sortWhich', sortWhich) let tableSort if (sortWhich.includes("name")) { tableSort = data.sort((a, b) => d3.ascending(a.name, b.name)) } else if (sortWhich.includes("dept")) { tableSort = data.sort((a, b) => d3.ascending(a.dept, b.dept)) } else if (sortWhich.includes('region')) { tableSort = data.sort((a, b) => d3.ascending(a.region, b.region)) } else { tableSort = data.sort((a, b) => d3.ascending(a.items, b.items)) } // Can I combine the above and pass a variable to a sort function? This is not working: // let tableSort = data.sort((a, b) => a.sortWhich - b.sortWhich) drawTable(tableSort) }) }
 html, body { height: 100%; margin: 0; } .grid { display: flex; flex-wrap: wrap; flex-direction: row; } .grid>div { display: flex; flex-basis: calc(100%/4 - 28px); justify-content: center; flex-direction: column; padding: 10px; } .box { margin: 0; } .box { color: #000; border: .5px solid #ccc; } .hrbox { background-color: #333; color: #fff; }
 <!DOCTYPE html> <html lang="en"> <head> <script src="https://d3js.org/d3.v6.min.js"></script> </head> <body> <div id="table"> <div class="grid"> <div class="box hrbox name"> <div>name</div> </div> <div class="box hrbox dept"> <div>dept</div> </div> <div class="box hrbox region"> <div>region</div> </div> <div class="box hrbox items"> <div>items</div> </div> </div> <div id="data-table"></div> </div> </body>

There are some problems here:这里有一些问题:

  • sort() sorts the array in place, no need for that tableSort variable sort()对数组进行原地排序,不需要tableSort变量
  • Removing the elements for painting the table again is not idiomatic D3, just use enter/update/exit selections.删除用于再次绘制表格的元素不是惯用的 D3,只需使用输入/更新/退出选择。

Regarding your secondary question, if you had the proper variable names you could just use bracket notation, removing all that if...else section:关于你的第二个问题,如果你有正确的变量名称,你可以使用括号表示法,删除所有if...else部分:

data.sort((a, b) => d3.ascending(a[sortWhich], b[sortWhich]))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM