Угловая труба - подстрока строки groupBy (пользовательская труба) - PullRequest
0 голосов
/ 10 января 2019

Я создал пользовательский канал для пользовательского группирования массива объектов по некоторому свойству:

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>

и это прекрасно работает!

Но я хочу заняться другим.

Внутренний пример (app.component): 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 голосов
/ 10 января 2019

Вы можете попробовать этот метод , чтобы сгруппировать их по их расширениям .

Также создал 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' ] } 
]
...