如果我有以下数据
[
{ person: 'john', age: 12 },
{ person: 'abby', age: 12 },
{ person: 'kyle', age: 14 },
]
我想要以下结果
[
[
{ person: 'john', age: 12 },
{ person: 'abby', age: 12 }
],
[
{ person: 'kyle', age: 14 }
]
]
正确的rxjs表达式是什么?我目前有
const grouped = source.pipe(
groupBy(person => person.age),
mergeMap(group => group.pipe(toArray()))
);
但是输出两次,这使我在Angular中的渲染变得混乱,因为我想渲染所有结果。
// First emit
[
{ person: 'john', age: 12 },
{ person: 'abby', age: 12 }
]
// Second emit
[
{ person: 'kyle', age: 14 }
]
编辑:如果可能的话,我也想看看如何变换对象。
示例输出
[
[
age: 12,
people: [
{ person: 'john', age: 12 },
{ person: 'abby', age: 12 }
]
],
[
age: 14,
people: [
{ person: 'kyle', age: 14 }
]
]
]
答案 0 :(得分:3)
您需要了解RxJs函数的功能以及RxJs映射函数的功能。 RxJs函数适用于流,如果要操作流中的单个值,则需要使用map将函数应用于所发出的项。您需要一个可用于数组而非流的groupBy函数。
groupBy(person => person.age)
您的代码中的这一行没有接收到任何人,而是在接收一群人。
您需要
const grouped = source.pipe(
map(people => groupBy(people, { keys: ['age'] }))
);
此可观察对象将发射一个分组的对象。在哪里可以找到将数组分组的函数?我在这里https://github.com/adriandavidbrand/ngx-ez/blob/master/projects/ngx-ez/src/lib/ez-core/functions/group-by.ts处写了一个https://stackblitz.com/edit/typescript-iwuzkw?file=group-by.ts的演示,但是对象的形状并不是您想要的。
[
[
key: { age: 12 },
items: [
{ person: 'john' },
{ person: 'abby' }
]
],
[
key: { age: 14 },
items: [
{ person: 'kyle' }
]
]
]
但是应该以您想要的方式使用。
可以肯定地将其简化,因为您不需要求和,然后按功能即可,但这是一个起点。
该功能是从我的Easy Angular库中导出的,即“ npm install ngx-ez”,然后您可以通过导入它
import { groupBy } from 'ngx-ez';
如果您不使用Angular,则可以忽略角度依赖性,因为该函数不需要Angular。
const { of } = rxjs;
const { map } = rxjs.operators;
const source$ = of([
{ person: 'john', age: 12 },
{ person: 'abby', age: 12 },
{ person: 'kyle', age: 14 },
]);
const sumGroup = (group, sum) => {
if (!sum || !sum.length || !group) {
return group;
}
return {
...group,
sum: sum.reduce(
(sumObj, sumProp) => ({
...sumObj,
[sumProp]: group.items.reduce((a, b) => resolveProperty(a, sumProp) + resolveProperty(b, sumProp))
}),
{}
)
};
};
const groupBy = (array, grouping) => {
if (!array) {
return array;
}
const keys = grouping.keys;
const groups = array.reduce((results, item) => {
const group = results.find(g => keys.every(key => item[key] === g.key[key]));
const data = Object.getOwnPropertyNames(item).reduce((o, prop) => {
if (!keys.some(key => key === prop)) {
o[prop] = item[prop];
}
return o;
}, {});
if (group) {
group.items.push(data);
} else {
results.push({
key: keys.reduce((o, key) => {
o[key] = item[key];
return o;
}, {}),
items: [data]
});
}
return results;
}, []);
return grouping.thenby
? groups.map(g => ({ ...g, items: groupBy(g.items, grouping.thenby) }))
: groups.reduce((arr, g) => {
arr.push(sumGroup(g, grouping.sum));
return arr;
}, []);
};
const grouped$ = source$.pipe(map(people => groupBy(people, { keys: ['age'] })));
grouped$.subscribe(grouped => { console.log(grouped); });
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.2/rxjs.umd.min.js"></script>