Angular 分组到键和值

Angular 分组到键和值,angular,rxjs,observable,grouping,partitioning,Angular,Rxjs,Observable,Grouping,Partitioning,下面以粗体显示的问题。鉴于这是我的HTML UI组件: <mat-tab label="Beginners"> <courses-card-list [courses]="coursesBeginners$ | async"> </courses-card-list> </mat-tab> <mat-tab label="Advanced"> <courses-card-list [courses]="courses

下面以粗体显示的问题。鉴于这是我的HTML UI组件:

<mat-tab label="Beginners">
  <courses-card-list [courses]="coursesBeginners$ | async">
  </courses-card-list>
</mat-tab>

<mat-tab label="Advanced">
  <courses-card-list [courses]="coursesAdvanced$ | async">
  </courses-card-list>
</mat-tab>
对于这一点:

let courses0: Course[] = [];
let courses1: Course[] = [];
courses$
  .pipe(
    map(courses => {
      courses.forEach(course => {
        if (course.categories.includes('BEGINNER')) {
          courses0.push(course);
        } else if (course.categories.includes('ADVANCED')) {
          courses1.push(course);
        }
      });
    }),
  )
  .subscribe(() => {
    this.coursesBeginners$ = of(courses0);
    this.coursesAdvanced$ = of(courses1);
  });
尽管第二个版本的代码更多,但效率更高,因为我们只在课程集合中迭代一次,而没有类别那么多顺便问一下,它能再短一点吗?

现在,我想做的是使用
groupBy
编写一个更高效的代码,如learnrxjs站点中的第二个示例所示,但是我很难将我的问题映射到示例中所示的简单问题-我的值是整个课程对象,而不仅仅是属性。我还尝试了rxjs文档中所示的方法,但我无法在没有编译错误的情况下通过
reduce
函数

我还意识到,基于
includes
方法进行划分可能很困难,在这种情况下,即使选择值
课程。如果没有其他方法,类别[0]
也是令人满意的


谢谢大家!

您可以静态定义可用的困难,然后使用它们在课程中循环,按困难类型对它们进行分组,然后您还可以在模板中使用它们,通过使用
ngForOf
为每个困难创建UI

import { Component } from '@angular/core';

import { of } from 'rxjs';
import { map, reduce, concatAll } from 'rxjs/operators';

enum CourseDifficulties {
  BEGINNER = 'BEGINNER',
  ADVANCED = 'ADVANCED',
  EXPERT = 'EXPERT',
};

const COURSES_DATA = [
  { name: 'Course 1', categories: [CourseDifficulties.BEGINNER, CourseDifficulties.ADVANCED] },
  { name: 'Course 2', categories: [CourseDifficulties.ADVANCED] },
  { name: 'Course 3', categories: [CourseDifficulties.EXPERT] },
  { name: 'Course 4', categories: [CourseDifficulties.EXPERT] },
  { name: 'Course 5', categories: [CourseDifficulties.ADVANCED] },
];

const AVAILABLE_DIFFICULTIES = [
  { name: 'Beginner', type: CourseDifficulties.BEGINNER },
  { name: 'Advanced', type: CourseDifficulties.ADVANCED },
  { name: 'Expert', type: CourseDifficulties.EXPERT },
];

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  public readonly difficulties = AVAILABLE_DIFFICULTIES;
  public readonly coursesByDifficulty$ = this.getCourses();



  public getCourses()
  {
    return of(COURSES_DATA).pipe(
      map(courses => courses.reduce((result, course) =>
      {
        this.difficulties.forEach(({ type }) =>
        {
          if(course.categories.indexOf(type) > -1)
          {
            result[type] = (result[type] || []).concat(course);
          }
        });
        return result;
      }, {}))
    );
  }
}

漂亮的解决方案cyr-x,感谢您在这方面花时间。我的目的也是添加枚举,因此感谢您为此付出了额外的努力。有一个问题:
返回结果
行后面的{}是
reduce
函数的累加吗?欢迎光临。是的,
{}
是累加器的初始值。现在让我贪婪地问一下:可以使用
groupBy
操作符来解决问题吗?这是解决问题的自然方式吗?我在类似的问题中成功地使用了它,但在Java 8中使用了它。如果一门课程只能属于一个难度类别,那么是的,如果不是(在我的解决方案中),我不明白为什么要在这里使用
groupBy
import { Component } from '@angular/core';

import { of } from 'rxjs';
import { map, reduce, concatAll } from 'rxjs/operators';

enum CourseDifficulties {
  BEGINNER = 'BEGINNER',
  ADVANCED = 'ADVANCED',
  EXPERT = 'EXPERT',
};

const COURSES_DATA = [
  { name: 'Course 1', categories: [CourseDifficulties.BEGINNER, CourseDifficulties.ADVANCED] },
  { name: 'Course 2', categories: [CourseDifficulties.ADVANCED] },
  { name: 'Course 3', categories: [CourseDifficulties.EXPERT] },
  { name: 'Course 4', categories: [CourseDifficulties.EXPERT] },
  { name: 'Course 5', categories: [CourseDifficulties.ADVANCED] },
];

const AVAILABLE_DIFFICULTIES = [
  { name: 'Beginner', type: CourseDifficulties.BEGINNER },
  { name: 'Advanced', type: CourseDifficulties.ADVANCED },
  { name: 'Expert', type: CourseDifficulties.EXPERT },
];

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  public readonly difficulties = AVAILABLE_DIFFICULTIES;
  public readonly coursesByDifficulty$ = this.getCourses();



  public getCourses()
  {
    return of(COURSES_DATA).pipe(
      map(courses => courses.reduce((result, course) =>
      {
        this.difficulties.forEach(({ type }) =>
        {
          if(course.categories.indexOf(type) > -1)
          {
            result[type] = (result[type] || []).concat(course);
          }
        });
        return result;
      }, {}))
    );
  }
}