简体   繁体   English

如何正确分组数组项

[英]How to group array items properly

I have a table and I want to render headers grouped by group property from object in array.我有一个表,我想呈现按数组中 object 的group属性分组的标题。 The array with the headers looks like this:带有标题的数组如下所示:

const headers = [
    { label: 'Date', group: '' },
    { label: 'Event', group: '' },
    { label: 'Days Out', group: '' },
    { label: 'T', group: 'Sales Velocity' },
    { label: '-1', group: 'Sales Velocity' },
    { label: '-2', group: 'Sales Velocity' },
    { label: '-3', group: 'Sales Velocity' },
    { label: '-4', group: 'Sales Velocity' },
    { label: 'Sold Last 5', group: 'Ticket Sales' },
    { label: 'Total Sold', group: 'Ticket Sales' },
    { label: 'Sellable cap.', group: 'Ticket Sales' },
    { label: '% sold', group: 'Ticket Sales' },
    { label: 'Availab.', group: 'Ticket Sales' },
    { label: 'Total', group: 'Revenue' },
    { label: 'Holds', group: 'Inventory Status' },
    { label: 'Comp', group: 'Inventory Status' },
    { label: 'Open', group: 'Inventory Status' },
    { label: 'Price cat.', group: 'Inventory Status' },
    { label: 'Avg. price', group: 'Stats' },
    { label: 'First time %', group: 'Stats' },
];

and the table component looks like this:表格组件如下所示:

<TableHead>
    <TableRow>
      {headers.map((header, index) => (
        <TableCellASHeader key={index}>
          <TableSortLabel
            active={header.column === sorting.orderBy}
            direction={sorting.orderDirection}
            onClick={() => onClickSort(header.column)}
            IconComponent={ArrowDropDownIcon}
          >
            {/* {header.group} */} // here I need to render group but only once per group
            {header.label}
          </TableSortLabel>
        </TableCellASHeader>
      ))}
    </TableRow>
  </TableHead>

What I want is to render header.group above header.label but only once per group, like on this picture below.我想要的是在header.group上方渲染header.label但每组只渲染一次,如下图所示。 Any code sample will be appreciated.任何代码示例将不胜感激。 在此处输入图像描述

First of all, I would club the headers into an object based on group.首先,我会将标头组合到基于组的 object 中。

const groupedHeaders = headers.reduce((acc, curr) => {
  let {group, label} = curr;
  if (!group) group = 'empty';
    if (!acc[group]) {
        acc[group] = [label]
    } else {
        acc[group] = [...acc[group], label]
    }
  return acc;
}, {});

After clubbing them up, the groupedHeaders would look like this -在将它们组合起来之后, groupedHeaders看起来像这样 -

{
  empty: [ 'Date', 'Event', 'Days Out' ],
  'Sales Velocity': [ 'T', '-1', '-2', '-3', '-4' ],
  'Ticket Sales': [
    'Sold Last 5',
    'Total Sold',
    'Sellable cap.',
    '% sold',
    'Availab.'
  ],
  Revenue: [ 'Total' ],
  'Inventory Status': [ 'Holds', 'Comp', 'Open', 'Price cat.' ],
  Stats: [ 'Avg. price', 'First time %' ]
}

Rendering in React part would make use of Object.entries() to iterate through the object and display accordingly.在 React 部分渲染将使用Object.entries()来遍历 object 并相应地显示。

Object.entries(groupedHeaders).map(([group, labels]) => {
  <TableRow>
      <HeaderGroup> // you will need to add css with flex/grid
         {group === 'empty' ? <EmptyHeader /> : <GroupHeader />}
         <SubHeaderGroup> // css required for grouping
           {labels.map((header, index) => (
             <TableCellASHeader key={index}>
               <TableSortLabel
                 active={header.column === sorting.orderBy}
                 ....
             </TableCellASHeader>
           ))}
         </SubHeaderGroup>
      </YourHeaderGroup>
   </TableRow>
});

Check out this Code Sandboxlink for the full version of code.查看此代码沙盒链接以获取完整版本的代码。

you can use new Set() and store group name in that and check each time when map function run.您可以使用new Set()并在其中存储组名称,并在每次 map function 运行时检查。 I have done this in javascript it will print group name 1 time and label many times., Check this我在 javascript 中完成了此操作,它将打印组名 1 次和 label 多次。,检查此

const headers = [
    { label: 'Date', group: '' },
    { label: 'Event', group: '' },
    { label: 'Days Out', group: '' },
    { label: 'T', group: 'Sales Velocity' },
    { label: '-1', group: 'Sales Velocity' },
    { label: '-2', group: 'Sales Velocity' },
    { label: '-3', group: 'Sales Velocity' },
    { label: '-4', group: 'Sales Velocity' },
    { label: 'Sold Last 5', group: 'Ticket Sales' },
    { label: 'Total Sold', group: 'Ticket Sales' },
    { label: 'Sellable cap.', group: 'Ticket Sales' },
    { label: '% sold', group: 'Ticket Sales' },
    { label: 'Availab.', group: 'Ticket Sales' },
    { label: 'Total', group: 'Revenue' },
    { label: 'Holds', group: 'Inventory Status' },
    { label: 'Comp', group: 'Inventory Status' },
    { label: 'Open', group: 'Inventory Status' },
    { label: 'Price cat.', group: 'Inventory Status' },
    { label: 'Avg. price', group: 'Stats' },
    { label: 'First time %', group: 'Stats' },
];

let groups = new Set();
headers.map((header) => {
    if(!groups.has(header.group)){
      groups.add(header.group);
      console.log(header.group); 
    } 
    console.log(header.label);
})

Output Output

Date
Event
Days Out
Sales Velocity
T
-1
-2
-3
-4
Ticket Sales
Sold Last 5
Total Sold
Sellable cap.
% sold
Availab.
Revenue
Total
Inventory Status
Holds
Comp
Open
Price cat.
Stats
Avg. price
First time %

You can alternatively use lodash/uniqBy to achieve this.您也可以使用 lodash/uniqBy 来实现这一点。 If you are working on enterprise level application and using React/Angular, it's worth considering.如果您正在开发企业级应用程序并使用 React/Angular,那么值得考虑。 You can achieve the desired result in one line like below-您可以在一行中达到所需的结果,如下所示 -

import uniqBy from ‘lodash/uniqBy’;

const modifiedArray = uniqBy(headers,’group’);

Also, it is always recommended to check beforehand if your data is undefined or not.此外,始终建议您事先检查您的数据是否未定义。 So, the best way to do is like below-所以,最好的方法如下 -

import get from ‘lodash/get’;

const modifiedArray = uniqBy((get(headers, ‘response.data’, [])),’group’);

Considering headers array is part of your api and the path is response.data.headers.考虑到 headers 数组是 api 的一部分,路径是 response.data.headers。

Please Note: You need to install lodash as your dev dependency in your project.请注意:您需要在项目中安装 lodash 作为您的开发依赖项。 uniqBy method will show only unique values without any duplication. uniqBy 方法将只显示唯一值而没有任何重复。

for example this code with filter and map and optionally put arrays into object例如,此代码带有filtermap并可选择将 arrays 放入 object

 const headers = [{ label: 'Date', group: '' }, { label: 'Event', group: '' }, { label: 'Days Out', group: '' }, { label: 'T', group: 'Sales Velocity' }, { label: '-1', group: 'Sales Velocity' }, { label: '-2', group: 'Sales Velocity' }, { label: '-3', group: 'Sales Velocity' }, { label: '-4', group: 'Sales Velocity' }, { label: 'Sold Last 5', group: 'Ticket Sales' }, { label: 'Total Sold', group: 'Ticket Sales' }, { label: 'Sellable cap.', group: 'Ticket Sales' }, { label: '% sold', group: 'Ticket Sales' }, { label: 'Availab.', group: 'Ticket Sales' }, { label: 'Total', group: 'Revenue' }, { label: 'Holds', group: 'Inventory Status' }, { label: 'Comp', group: 'Inventory Status' }, { label: 'Open', group: 'Inventory Status' }, { label: 'Price cat.', group: 'Inventory Status' }, { label: 'Avg. price', group: 'Stats' }, { label: 'First time %', group: 'Stats' }, ]; const empty = headers.filter(el => el.group === '').map(el => el.label) console.log('empty', empty) const sales = headers.filter(el => el.group === 'Sales Velocity').map(el => el.label) console.log('sales', sales) const ticket = headers.filter(el => el.group === 'Ticket Sales').map(el => el.label) console.log('ticket', ticket) const revenue = headers.filter(el => el.group === 'Revenue').map(el => el.label) console.log('revenue', revenue) const inventory = headers.filter(el => el.group === 'Inventory Status').map(el => el.label) console.log('inventory', inventory) const stats = headers.filter(el => el.group === 'Stats').map(el => el.label) console.log('stats', stats) const obj = {} obj.empty = empty obj.sales = sales obj.ticket = ticket obj.revenue = revenue obj.inventory = inventory obj.stats = stats console.log('obj', obj)

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

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