从对象数组生成表

时间:2019-02-03 16:51:24

标签: javascript

好,所以我有一系列看起来像这样的对象

{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"}

我希望能够生成一个看起来像这样的表

enter image description here

我想我必须过滤或分组一些键-值对或类似的东西,但是我不知道正确的方法。

同样,对于这个特定的表,我必须执行以下操作:

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

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

但是随后我必须弄清楚如何用此数据填充HTML表本身。 也许有一些图书馆或其他可以帮助我做到这一点的东西。谢谢!

2 个答案:

答案 0 :(得分:1)

您可以构建一棵树并收集数据集中的所有值。结果是一棵树,其中的键是locationcolorsize的值。在叶子处,您可以获得free的累加值。

然后您可以使用累积值为表构建一个数组。

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; }

答案 1 :(得分:1)

  

查看最后生成的表格

您可以使用缩小来累积每种颜色和每个位置的尺寸。这是使用reduce和结果树的示例方法。

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
    }
  }
}

要创建表,您可以遍历位置条目,并针对每个位置遍历颜色,然后将行附加到表中。

您可以通过克隆从DOM查询的行模板来创建每一行,然后将该行添加到表主体中:

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>