Angular Pipe-字符串的groupBy子字符串(自定义管道)

时间:2019-01-10 09:51:28

标签: javascript angular typescript pipe

我通过一些属性为对象的自定义分组数组创建了一个自定义管道:

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({name: 'groupBy'})
export class GroupByPipe implements PipeTransform {
  transform(value: Array<any>, field: string): Array<any> {
  const groupedObj = value.reduce((prev, cur)=> {
      if(!prev[cur[field]]) {
        prev[cur[field]] = [cur];
      } else {
        prev[cur[field]].push(cur);
      }
      return prev;
    }, {});

    return Object.keys(groupedObj).map(key => ({ key:key, value: groupedObj[key] }));
  }
}

    <div>
      <h2>Group by department</h2>
<ul>
    <li *ngFor="let group of employees | groupBy:'department'">Department{{group.key}}
        <ul>
            <li *ngFor="let event of group.value">
            {{event.firstName}} {{event.lastName}}
            </li>
        </ul>
    </li>
</ul>

这很完美!

但是我想做另一件事。

内部示例(应用组件): https://stackblitz.com/edit/angular-rc3njv

我有一个字符串数组:

 email = ["bla@gmail.com", "ggg@gmail.com", "zzz@gmail.com","mmm@hotmail.com"]

,我想按子字符串将该数组分组。例如:  @ gmail.com是一个群组,包含“ bla@gmail.com”,“ ggg@gmail.com”,“ zzz@gmail.com”; @hotmail是另一个组,包含“ mmm@hotmail.com”

有人知道如何自定义示例中实现的管道,以便按子字符串对字符串数组进行分组吗?

非常感谢!

1 个答案:

答案 0 :(得分:1)

您可以尝试此方法,根据扩展名将其分组。

还创建了 Stackblitz Demo 供您参考

  

您的样本数据: const emails = ["bla@gmail.com", "ggg@gmail.com", "zzz@gmail.com","mmm@hotmail.com"];


  

方法1-采用{ '@gmail.com': ['...', '...'] }格式

// Fetches the extensions from the emails, used new Set to avoid duplicates
// Result: [ '@gmail.com', '@hotmail.com' ]
const extensions = Array.from(new Set(emails.map(email => email.match(/@.*/ig)[0])));    


// Returns an index of the extension from extensions (list above) if the condition met where the email passed has a keyword of either from these two [ '@gmail.com', '@hotmail.com' ]
// Result: e.g bla@gmail.com -> 0 as '@gmail.com' is found on index 0 of extensions [ '@gmail.com', '@hotmail.com' ]
const getEmailExtensionIndex = email => extensions.findIndex(extension => email.includes(extension));


// Group them based on their extensions
const result = emails.reduce((acc, email) => {
  // Get the extension of the specified email e.g bla@gmail.com -> @gmail.com
  const extension = extensions[getEmailExtensionIndex(email)];     

  // If example @gmail.com key doesn't exist inside the object acc, specify an initial value
  if (!acc[extension]) acc[extension] = [];    

  // Push the email to it's corresponding key inside the object
  // If extension is equal to '@gmail.com' then { '@gmail.com': [ 'bla@gmail.com' ] } and so on
  acc[extension].push(email);

  return acc;
}, {});

结果:

{
  '@gmail.com': [ 'bla@gmail.com', 'ggg@gmail.com', 'zzz@gmail.com' ],
  '@hotmail.com': [ 'mmm@hotmail.com' ]
}

  

方法2-采用[ { key: '' , values: [] } ]格式

// result is from the Method #1 const result = emails.reduce(...)
const result2 =  Object.keys(result).map(key => ({ key, values: result[key] }));

结果:

[ 
   { key: '@gmail.com', values: [ 'bla@gmail.com', 'ggg@gmail.com', 'zzz@gmail.com' ] },
   { key: '@hotmail.com', values: [ 'mmm@hotmail.com' ] } 
]