以下粗体中的问题。鉴于这是我的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>
我有一个可观察的课程,我需要根据每个课程的类别将其过滤为多个可观察的内容。为简便起见,我将示例限制为两类。我从Angular 7应用程序的ts组件中摘录了该片段:
this.beginnersCourses$ = this.courses$.pipe(
map(courses => courses.filter(
course => course.categories.includes("BEGINNER"))));
this.advancedCourses$ = this.courses$.pipe(
map(courses => courses.filter(
course => course.categories.includes("ADVANCED"))));
对此:
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网站的第二个示例中的here所示,但我是在将我的问题映射到示例中显示的简单问题时遇到了麻烦-我的值是整个课程对象,而不仅仅是属性。我还尝试了rxjs文档中的here中显示的方法,但是我没有遇到reduce
函数而没有编译错误。
我还意识到可能很难基于includes
进行分区,在这种情况下,如果没有其他方法,即使选择值course.categories[0]
也是令人满意的。
谢谢!
答案 0 :(得分:1)
您可以静态定义可用的困难,然后使用它们遍历课程以按难度类型对它们进行分组,然后还可以在模板中使用它们来使用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;
}, {}))
);
}
}