我有一个Observable<Recipe[]>
,我希望将其缩减为另一个类ChartData[]
的数组,以用作高图图表(列和饼图)的数据源。
我正在尝试使用Observable<Recipe[]>
上的RxJS管道运算符来调用我的数据上的reduce运算符,但我无法使其工作? reduce
运算符不会迭代我Observable<Recipe[]>
中的项目。以下是我的尝试:
this.foodService.getAllReceipes()
.pipe(
reduce((array: ChartData[], value: Recipe[], i: number) => {
const author = this.createOrFindAuthor(array, value[i]);
author.y += 1;
return array;
}, new Array<ChartData>())
)
.subscribe(data => this.chartData$ = of(data.sort((a, b) => b.y - a.y)));
}
getAllRecipes()
返回Observable<Recipe[]>
this.chartData$
是Observable<ChartData[]>
我正在尝试将此缩减为ChartData[]
。我已经能够在subscribe
运算符中执行此操作,图表显示了预期的数据,但我认为我应该能够将其作为可管理的运算符执行?以下是作为订阅的一部分进行的简化:
this.foodService.getAllReceipes()
.subscribe((data) => {
const list = data.reduce((arr: ChartData[], v: Recipe) => {
const author = this.createOrFindAuthor(arr, v);
author.y += 1;
return arr;
}, new Array<ChartData>());
this.chartData$ = of(list.sort((a, b) => b.y - a.y));
});
我已尝试在可管道subscribe
中使用reduce
代码,但我收到编译错误,指出该方法需要Recipe[]
作为值。但是如果我使用数组,那么我只从Observable得到第一个元素(或者我只是得到了Observable并且需要对它做些什么?)
这是可能的还是我的思维过程在可管理操作符应该如何处理Observable时是错误的?
这里有参考模型和createOrFindAuthor函数:
export class Recipe {
public Title: string;
public Author: string;
public Source: string;
public Page: number;
public Link?: string;
}
export class ChartData {
name: string;
y: number;
}
private createOrFindAuthor(array: ChartData[], recipe: Recipe): ChartData {
const name = (recipe.Author.length > 0 ? recipe.Author : 'UNKNOWN');
let found = array.find(i => i.name === name);
if (!found) {
const newData = new ChartData();
newData.name = name;
newData.y = 0;
array.push(newData);
found = newData;
}
return found;
}
答案 0 :(得分:3)
所以Chau Tran让我走上了正确的路线。显然,我需要将switchMap
观察到Recipe[]
,然后reduce
运算符很乐意接受Recipe
作为值。解决方法如下:
this.foodService.getAllReceipes()
.pipe(
switchMap(data => data as Recipe[]), <<== ADDED THIS
reduce((array: ChartData[], value: Recipe) => {
const author = this.createOrFindAuthor(array, value);
author.y += 1;
return array;
}, new Array<ChartData>()),
switchMap(data => this.chartData$ = of(data.sort((a, b) => b.y - a.y)))
)
.subscribe();
答案 1 :(得分:1)
在reduce
之后,尝试:
switchMap(data => {
this.chartData$ = of(data.sort((a, b) => b.y - a.y));
return this.chartData$;
})
.subscribe()
答案 2 :(得分:0)
我创建了此stackblitz example以演示reduce()
的演示用法。该项目包含其他内容,但您需要的是demoReduce.ts
:
import { Observable, of } from 'rxjs'
import { reduce, tap } from 'rxjs/operators'
type Book = {
title: string
noPages: number
}
type Library = {
totalPages: number
books: Book[]
}
export const demoReduce = () => {
const books$: Observable<Book> = of(
{ title: 'book 1', noPages: 10 },
{ title: 'book 2', noPages: 20 },
{ title: 'book 3', noPages: 30 },
)
return books$.pipe(
// --- reduce a stream of "Book" into a "Library"
reduce<Book, Library>((previous, book) => {
// --- add book to "Library" and increment totalPages in "Library"
return {
totalPages: previous.totalPages + book.noPages,
books: [
...previous.books,
book
]
}
}, { totalPages: 0, books: [] }),
tap(val => console.log(val))
)
}
要执行observable,请使用“Demo Reduce”按钮,然后查看控制台。
它将Books
的流转换为单个Library
对象。
注意:
reduce()
的在线编辑器中显示错误(波浪形的红色下划线)。我没有在IntelliJ / WebStorm中得到错误。我怀疑是一个stackblitz错误。更新
这是将Observable<Book[]>
作为输入(未测试)的相同功能:
export const demoReduceWithArray = () => {
const books$: Observable<Book[]> = of([
{ title: 'book 1', noPages: 10 },
{ title: 'book 2', noPages: 20 },
{ title: 'book 3', noPages: 30 }
])
return books$.pipe(
// --- reduce a stream of "Book[]" into a "Library"
reduce<Book[], Library>((previous, books) => {
// --- add each book to "Library" and increment totalPages in "Library"
books.map(book => {
previous = {
totalPages: previous.totalPages + book.noPages,
books: [
...previous.books,
book
]
}
})
return previous
}, { totalPages: 0, books: [] }),
tap(val => console.log(val))
)
}