【问题标题】:How to show values of the same item for different date in react.js如何在 react.js 中显示不同日期的同一项目的值
【发布时间】:2021-03-30 00:55:39
【问题描述】:

我有数组:

array = [
  {
    "id": 1,
    "date": {
      "id": 1,
      "name": "202001"
    },
    "item": {
      "id": 1,
      "name": "I1"
    },
    "price": 100
    },
    {
    "id": 2,
    "date": {
      "id": 2,
      "name": "202002"
    },
    "item": {
      "id": 1,
      "name": "I1"
    },
    "price": 200
  },
  {
    "id": 3,
    "date": {
      "id": 2,
      "name": "202002"
    },
    "item": {
      "id": 2,
      "name": "I2"
    },
    "price": 300
  },
]

并且我希望能够显示如表所示的数据:

ITEM 202001 202002
I1 100 200
I2 - 300

这个想法是将每个日期的值分组为同一项目。

我该怎么做,建议?

【问题讨论】:

标签: javascript arrays json reactjs datatables


【解决方案1】:

您可以将整个结构简化为按项目名称索引的字典,其值是按日期索引的字典:

items_dicc = array.reduce((acc, e) => {
  if (!acc[e["item"]["name"]]) {
    acc[e["item"]["name"]] = {
      [e["date"]["name"]]: e["price"]
    }
  } else {
    acc[e["item"]["name"]][e["date"]["name"]] = e["price"]
  }
  return acc
}, {})

/* items_dicc holds:
{ I1: { '202001': 100, '202002': 200 }, I2: { '202002': 300 } }
*/

随后,您可以利用items_dicc 结构来构建您要查找的表:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <table>
    <thead>
      <tr class="thead">
        <th>ITEM</th>
      </tr>
    </thead>
    <tbody class="tbody">
      <tr>
        <td></td>
      </tr>
    </tbody>
  </table>

</body>

<script>
  array = [
    {
      "id": 1,
      "date": {
        "id": 1,
        "name": "202001"
      },
      "item": {
        "id": 1,
        "name": "I1"
      },
      "price": 100
    },
    {
      "id": 2,
      "date": {
        "id": 2,
        "name": "202002"
      },
      "item": {
        "id": 1,
        "name": "I1"
      },
      "price": 200
    },
    {
      "id": 3,
      "date": {
        "id": 2,
        "name": "202002"
      },
      "item": {
        "id": 2,
        "name": "I2"
      },
      "price": 300
    }
  ]

  items_dicc = array.reduce((acc, e) => {
    if (!acc[e["item"]["name"]]) {
      acc[e["item"]["name"]] = {
        [e["date"]["name"]]: e["price"]
      }
    } else {
      acc[e["item"]["name"]][e["date"]["name"]] = e["price"]
    }
    return acc
  }, {})

  // Compute dates that will be used as headers. Duplicates are removed after creating a set and turning it into a list again
  dates = [...new Set(Object.keys(items_dicc).map(i => Object.keys(items_dicc[i])).flat())]


  const thead = document.getElementsByClassName("thead")[0]
  const tbody = document.getElementsByClassName("tbody")[0]

  dates.forEach(date => {
    thead.appendChild(
      htmlToElement(`<th>${date}</th>`)
    )
  });

  Object.keys(items_dicc).forEach(i => {
    let row = `<tr><td>${i}</td>`
    dates.forEach(date => {
      row = `${row}<td>${items_dicc[i][date] || ''}</td>`
    });
    row = `${row}</tr>`
    tbody.appendChild(htmlToElement(row))
  })

  // From https://stackoverflow.com/questions/494143/creating-a-new-dom-element-from-an-html-string-using-built-in-dom-methods-or-pro/35385518#35385518
  function htmlToElement(html) {
    var template = document.createElement('template');
    html = html.trim();
    template.innerHTML = html;
    return template.content.firstChild;
  }

</script>

</html>

最终结果:

<table>
  <thead>
    <tr class="thead">
      <th>ITEM</th>
      <th>202001</th>
      <th>202002</th>
    </tr>
  </thead>
  <tbody class="tbody">
    <tr>
      <td></td>
    </tr>
    <tr>
      <td>I1</td>
      <td>100</td>
      <td>200</td>
    </tr>
    <tr>
      <td>I2</td>
      <td></td>
      <td>300</td>
    </tr>
  </tbody>
</table>

编辑:最简单的React 版本的解决方案:

App.js

function App() {
  const array = [
    {
      "id": 1,
      "date": {
        "id": 1,
        "name": "202001"
      },
      "item": {
        "id": 1,
        "name": "I1"
      },
      "price": 100
    },
    {
      "id": 2,
      "date": {
        "id": 2,
        "name": "202002"
      },
      "item": {
        "id": 1,
        "name": "I1"
      },
      "price": 200
    },
    {
      "id": 3,
      "date": {
        "id": 2,
        "name": "202002"
      },
      "item": {
        "id": 2,
        "name": "I2"
      },
      "price": 300
    }
  ]

  const items_dicc = array.reduce((acc, e) => {
    if (!acc[e["item"]["name"]]) {
      acc[e["item"]["name"]] = {
        [e["date"]["name"]]: e["price"]
      }
    } else {
      acc[e["item"]["name"]][e["date"]["name"]] = e["price"]
    }
    return acc
  }, {})

  // Compute dates that will be used as headers. Duplicates are removed after creating a set and turning it into a list again
  const dates = [...new Set(Object.keys(items_dicc).map(i => Object.keys(items_dicc[i])).flat())]

  return (
    <div className="App">
      <table>
        <thead>
          <tr>
            <th>ITEM</th>
            {dates.map(date => <th>{date}</th>)}
          </tr>
        </thead>
        <tbody>
          {
            Object.keys(items_dicc).map((item) => {
              return (
                <tr>
                  <td>{item}</td>
                  {dates.map((date) => <td>{items_dicc[item][date] || ''}</td>)}
                </tr>
              )
            })
          }
        </tbody>
      </table>
    </div>
  );
}

export default App;

【讨论】:

  • 非常感谢!我很欣赏你所做的!看起来不错!如何在 react.js 中做同样的事情?
  • 不客气 =)。我编辑了答案,以便您可以看到解决方案的React 版本
  • 如果我想添加功能以在弹出窗口中显示项目的更多详细信息,它会是什么样的?
  • 嗯,我建议为此发布一个新问题,因为它与原始问题完全无关
  • 好的,我会做的。谢谢!
猜你喜欢
  • 2021-03-30
  • 2021-05-27
  • 1970-01-01
  • 2021-08-15
  • 1970-01-01
  • 2015-02-20
  • 2012-11-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多