简体   繁体   中英

Generate a table from array of objects

Ok, so I have an array of objects that look like that

{id: 1, color: "red", size: "S", free: 14, location: "Location #1"}
{id: 2, color: "green", size: "M", free: 5, location: "Location #1"}
{id: 3, color: "red", size: "M", free: 3, location: "Location #2"}
{id: 4, color: "green", size: "L", free: 12, location: "Location #1"}
{id: 5, color: "green", size: "S", free: 5, location: "Location #2"}
{id: 6, color: "red", size: "L", free: 0, location: "Location #1"}
{id: 7, color: "blue", size: "L", free: 0, location: "Location #2"}
{id: 8, color: "blue", size: "M", free: 0, location: "Location #1"}
{id: 9, color: "blue", size: "S", free: 0, location: "Location #1"}
{id: 10, color: "purple", size: "L", free: 0, location: "Location #2"}

And I want to be able to generate a table that would look something like that

在此处输入图片说明

I suppose that i have to filter or group some of the key-value pairs or something like that but i don't know the right way to approach this.

Again maybe for this particular table I have to do something like this:

{
  color: 'red',
  location: 'Location #1',
  sizes: [
    {
      s: 12
    },
    {
      m: 5
    },
    {
      l: 7
    }
  ]
}

{
  color: 'green',
  location: 'Location #1',
  sizes: [
    {
      s: 3
    },
    {
      m: 11
    },
    {
      l: 4
    }
  ]
}

But then i have to figure out how to populate the HTML table itself with this data. Maybe there is some library or something that would help me do that. Thanks!

You could build a tree and collect al value you have in your data set. The result is a tree where the keys are the location , color and size values. At the leaves, you get the accumulated value of free .

Then you could build a array for the table with the accumulated values.

 function getTable(object) { function getRows(object, row = []) { if (row.length === 2) { table.push(row.concat(['S', 'M', 'L'].map(k => object[k] || 0))); return; } Object.entries(object).forEach(([k, v]) => getRows(v, row.concat(k))); } var table = []; getRows(object); return table; } var data = [{ id: 1, color: "red", size: "S", free: 14, location: "Location #1" }, { id: 2, color: "green", size: "M", free: 5, location: "Location #1" }, { id: 3, color: "red", size: "M", free: 3, location: "Location #2" }, { id: 4, color: "green", size: "L", free: 12, location: "Location #1" }, { id: 5, color: "green", size: "S", free: 5, location: "Location #2" }, { id: 6, color: "red", size: "L", free: 0, location: "Location #1" }, { id: 7, color: "blue", size: "L", free: 0, location: "Location #2" }, { id: 8, color: "blue", size: "M", free: 0, location: "Location #1" }, { id: 9, color: "blue", size: "S", free: 0, location: "Location #1" }, { id: 10, color: "purple", size: "L", free: 0, location: "Location #2" }], tree = data.reduce((r, o) => { var q = ['location', 'color'].reduce((p, k) => p[o[k]] = p[o[k]] || {}, r); q[o.size] = (q[o.size] || 0) + o.free; return r; }, {}), table = getTable(tree); console.log(tree); console.log(table); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

See the table generated at the end

You can use reduce to accumulate the sizes for each color and each location. Here is an example way to use reduce and the resulting tree.

const tree = data.reduce((accum, { id, color, size, free, location }) => {
  accum[location] = accum[location] || { };
  accum[location][color] = accum[location][color] || { S: 0, M: 0, L: 0 };
  accum[location][color][size] += free;
  return accum;
}, {});
{
  "Location #1": {
    "red": {
      "S": 14,
      "M": 0,
      "L": 0
    },
    "green": {
      "S": 0,
      "M": 5,
      "L": 12
    },
    "blue": {
      "S": 0,
      "M": 0,
      "L": 0
    }
  },
  "Location #2": {
    "red": {
      "S": 0,
      "M": 3,
      "L": 0
    },
    "green": {
      "S": 5,
      "M": 0,
      "L": 0
    },
    "blue": {
      "S": 0,
      "M": 0,
      "L": 0
    },
    "purple": {
      "S": 0,
      "M": 0,
      "L": 0
    }
  }
}

To create the table, you can iterate over the location entries, and for each location iterate over the colors, then append the rows to the table.

You can create each row by cloning a row template that you query from the DOM, then append that row to your table body:

 const data = [ {id: 1, color: "red", size: "S", free: 14, location: "Location #1"}, {id: 2, color: "green", size: "M", free: 5, location: "Location #1"}, {id: 3, color: "red", size: "M", free: 3, location: "Location #2"}, {id: 4, color: "green", size: "L", free: 12, location: "Location #1"}, {id: 5, color: "green", size: "S", free: 5, location: "Location #2"}, {id: 6, color: "red", size: "L", free: 0, location: "Location #1"}, {id: 7, color: "blue", size: "L", free: 0, location: "Location #2"}, {id: 8, color: "blue", size: "M", free: 0, location: "Location #1"}, {id: 9, color: "blue", size: "S", free: 0, location: "Location #1"}, {id: 10, color: "purple", size: "L", free: 0, location: "Location #2"} ]; const tree = data.reduce((accum, { id, color, size, free, location }) => { accum[location] = accum[location] || { }; accum[location][color] = accum[location][color] || { S: 0, M: 0, L: 0 }; accum[location][color][size] += free; return accum; }, {}); const tpl = document.querySelector('#row-template'); const tbody = document.querySelector("tbody"); Object.entries(tree).forEach(([location, values]) => { Object.entries(values).forEach(([color, sizes]) => { const clone = document.importNode(tpl.content, true); const td = clone.querySelectorAll("td"); td[0].textContent = location; td[1].textContent = color; td[2].textContent = sizes['S']; td[3].textContent = sizes['M']; td[4].textContent = sizes['L']; tbody.appendChild(clone); }); }); 
 table { border-collapse: collapse; } thead { font-weight: bold; } td { padding: 5px; border: 1px solid black; } 
 <template id="row-template"> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> </template> <table id="data-table"> <thead> <tr> <td>Location</td><td>color</td><td>S</td><td>M</td><td>L</td> </tr> </thead> <tbody> </tbody> </table> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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