React groupBy并打印到表格中

时间:2019-05-29 18:13:39

标签: arrays reactjs sorting lodash

编辑: 方法groupBy,omit和mapValue从以下位置导入:

import groupBy from 'lodash/groupBy';
import mapValues from 'lodash/mapValues';
import omit from 'lodash/omit';

我有这个json

[{
    "name": "Jitka",
    "orderNumber": "1",
    "order": false
},
{
    "name": "Jitka",
    "orderNumber": "0",
    "order": false
},
{
    "name": "Petr",
    "orderNumber": "6",
    "order": false
}]

在反应中,我需要按名称分组值。分组后,我需要将数据以格式打印到表中

enter image description here 问题是,如何将我按名字分组的数据转换成这种格式的表。

我的代码是:

{
        const ordersByName = groupBy(this.state && this.state.orders, 'name');
        let order = mapValues(ordersByName, x => x.map(y => omit(y, 'name')));
        this.state.sortedOrders.push(order);

    }

    return (
        <div>
            <MyNavbar/>
            <div className="container">
                <table className="table">
                    <tbody>
                    <tr>
                        <th>Name</th>
                        <th>Order number</th>
                        <th>Order</th>
                    </tr>
                    {this.state.sortedOrders.map((offer) => {
                        console.log(offer);

                    })}
                    </tbody>
                </table>
            </div>
        </div>

谢谢。

2 个答案:

答案 0 :(得分:0)

由于您实际上是在orderNumber上进行分组,因此需要首先减少您的数据。因此,由于您已经在使用lodash,因此可以尝试执行以下操作:

let data = _(this.state.sortedOrders) // <-- chain this array via _.chain
  .groupBy('name')  // <-- group by name first
  .mapValues(arr =>  // <-- map through the values of the object from groupBy
    _.mergeWith(  // <-- merge the grouped by name records
      ..._.sortBy(arr, 'orderNumber'),  // <-- sort the array by `orderNumber`
      (o, s, k) => _.isEqual(k, 'orderNumber') ? o + (s ? ',' + s : '') : o)
  )
  .values() // <-- get the values of the final object
  .value()  // <-- get the final result from the chaining

然后您的渲染将是:

<div>
  <MyNavbar/>
  <div className="container">
    <table className="table">
      <tbody>
        <tr>
          <th>Name</th>
          <th>Order number</th>
          <th>Order</th>
        </tr>
        {data.map(offer => (
        <tr>
            <td>{offer.name}</td>
            <td>{offer.orderNumber}</td>
            <td>{offer.order}</td>
        </tr>
        ))}
      </tbody>
    </table>
  </div>
</div>

简而言之,您需要让data看起来像这样:

let data = [{ "name": "Jitka", "orderNumber": "1", "order": false }, { "name": "Jitka", "orderNumber": "0", "order": false }, { "name": "Petr", "orderNumber": "6", "order": false } ]

let result = _(data)
  .groupBy('name')
  .mapValues(arr =>
    _.mergeWith(
      ..._.sortBy(arr, 'orderNumber'),
      (o, s, k) => _.isEqual(k, 'orderNumber') ? o + (s ? ',' + s : '') : o)
  )
  .values()  
  .value()

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

您可以看到您有2条记录,而不是最初的3条记录,因为我们通过orderNumber合并了其中两条。

这显然可以通过Array.reduce / Array.sort等完成,但是由于您已经在使用lodash,因此可以简单地利用其groupBy/mergeWith等功能。

答案 1 :(得分:0)

此解决方案使用_.flow()创建合并组功能。该函数接受一个iteratee(任何可以使用_.groupBy()的iteratee),以及一个应作为数组收集的键列表。结果是一个新功能,该功能可以按迭代器分组,然后合并每个组,并合并collectKeys中任何键的值:

const { flow, partialRight: pr, groupBy, map, mergeWith } = _; // simulates separate imports

const combineGroups = (iteratee, collectKeys) => flow(
  pr(groupBy, iteratee),
  pr(map, group => mergeWith({}, ...group, (t = [], s, k) => 
    collectKeys.includes(k) ? [...t, s] : s)
  )
);

const combineGroupsByName = combineGroups('name', ['orderNumber']);

const Demo = ({ orders }) => {
  const ordersByName = combineGroupsByName(orders);

  return (
    <div className="container">
        <table className="table">
            <tbody>
            <tr>
                <th>Name</th>
                <th>Order number</th>
                <th>Order</th>
            </tr>
            {ordersByName.map(({ name, orderNumber, order }) => (
              <tr>
                  <td>{name}</td>
                  <td>{orderNumber.sort().join(', ')}</td>
                  <td>{order.toString()}</td>
              </tr>
            ))}
            </tbody>
        </table>
    </div>
  );
};

const orders = [{"name":"Jitka","orderNumber":"1","order":false},{"name":"Jitka","orderNumber":"0","order":false},{"name":"Petr","orderNumber":"6","order":false}];

ReactDOM.render(
  <Demo orders={orders} />,
  demo
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="demo"></div>