Angular / ngrx - 来自州

时间:2017-05-20 14:50:59

标签: angular typescript rxjs ngrx-store

我试图弄清楚如何从一个对象列表中获取一个分组和聚合的值数组(我可以使用ngFor),对于我的生活,我无法使它工作。 数据(我的状态的一部分)看起来像这样:

[{name: "A", value: 1, desc: 'something irrelevant'}, 
 {name: "A", value: 3, desc: 'also other properties'}, 
 {name: "B", value: 2, desc: 'etc.'}, 
 {name: "B", value: 5, desc: 'etc.'}]

我试图得到的结果是(注意类型不同):

[{name: "A", value: 4}, {name: "B", value: 7}]

所以,基本上我想找到不同的名字"以及"值"的总和对于具有该名称的所有对象,其输出可由ngFor |使用异步。

我的几乎正常工作的解决方案,目前获取不同的值是:

       this.aggregates:Observable<any[]> = this.store
        .select(state => state.valuesList)
        .map(valuesList => valuesList.sort((a,b) => {return (a.name > b.name) ? 1 : ((b.name > a.name) ? -1 : 0);} }))
        .flatMap(valuesList => valuesList)
        .map(value => value.name)
        .distinct();

我很高兴从这开始;问题是,如果我没有添加toArray(),那么Typescript会抱怨&#34; Type字符串不能分配给任何[]&#34 ;;如果我在distinct()之后添加了toArray(),它就不会再抱怨了,但是subscribe()不会产生任何结果。

我做错了什么?我应该将所有东西都移到减速器上(但是我不知道我是否可以改变同一减速器中不同动作返回的物体类型)? 非常感谢任何帮助。

更新: 我有一个工作groupBy()实现更高兴,因为它应该是它的用例。

2 个答案:

答案 0 :(得分:3)

您可以使用groupBy执行您想要的操作,但必须对从列表派生的observable使用groupBy运算符 - 因为groupBy需要一个可观察的项目。< / p>

在以下代码段中,slice相当于this.store.select(state => state.valuesList)

&#13;
&#13;
const slice = Rx.Observable.of([
  { name: "A", value: 1, desc: "something irrelevant" },
  { name: "A", value: 3, desc: "also other properties" },
  { name: "B", value: 2, desc: "etc." },
  { name: "B", value: 5, desc: "etc." }
]);

const grouped = slice.concatMap(list => Rx.Observable
  .from(list)
  .groupBy(item => item.name)
  .mergeMap(group => group
    .reduce((total, item) => total + item.value, 0)
    .map(total => ({ name: group.key, value: total }))
  )
  .toArray()
);

grouped.subscribe(value => console.log(value));
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
<script src="https://unpkg.com/rxjs@5/bundles/Rx.min.js"></script>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

这样的事情:

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/from';
import 'rxjs/add/operator/map';

function main() {
    const t = [
        { name: "C", value: 3, desc: 'also other properties' },
        { name: "A", value: 1, desc: 'something irrelevant' },
        { name: "B", value: 2, desc: 'etc.' },
        { name: "A", value: 3, desc: 'also other properties' },
        { name: "B", value: 5, desc: 'etc.' }
    ];

    const store = Observable.from(Array(100).fill(t));

    const aggregates: Observable<any[]> = store
    .map((valuesList) => valuesList
        .map((x) => ({ name: x.name, value: x.value }))
        .sort((a, b) => a.name.localeCompare(b.name))
        .reduce((pre, cur) => {
            const len = pre.length - 1;

            if (pre[len] && pre[len].name === cur.name) {
                pre[len].value += cur.value;
                return pre;
            }
            pre[len + 1] = cur;
            return pre;
        }, [])
    );

    return aggregates;
}

main().subscribe((x) => {
    console.dir(x, { depth: null });
});

输出结果为:

[ { name: 'A', value: 4 },
  { name: 'B', value: 7 },
  { name: 'C', value: 3 } ]
[ { name: 'A', value: 4 },
  { name: 'B', value: 7 },
  { name: 'C', value: 3 } ]
[ { name: 'A', value: 4 },....