我想总结测试成绩,我的数据看起来像这样
{ testResult:
{ foo:
{foo1: x},
{foo2: y}
},
{ bar:
{bar1: z}
'foo'和'bar'是有意义的问题子类别,子节点包含questionID和相应的分数。我需要总结按类别排序的分数。我像这样查询列表
let res = this._dbref.database.list('/bmzi-answers',{
query: {
orderByKey: true,
equalTo: id
}
})
并使用{{ res | async | json }}
显示结果向我显示该查询有效。我得到像
[{"cat1":3, "cat2":3, "cat3":3, "$key":"cat"}]
如何减少组件逻辑中的值,以获得标记为cat *?
的所有问题的总和我理解像filter / map / reduce这样的概念,但我是Reactive Javascript,Angular2和AngularFire的新手。
请提前帮助并表示感谢!
编辑: 所有孩子都有猫前缀,这是域/问卷的一部分。这段代码
let res = this.dbRef.database.list(`/bmzi-answers/${id}`)
.do((array) => { console.log(JSON.stringify(array)); })
.map((array) => array
.reduce((acc, element) => acc + element.$value, 0)
)
let score = res.subscribe(sum => {
console.log("score: " + sum)
});
return score;
在第一次调用时生成此控制台输出:
[
{ "$key": "cat1", "$value": 3 },
{ "$key": "cat2", "$value": 3 },
{ "$key": "cat3", "$value": 3 }
]
score: [object Object]
第二次:
[]
score: undefined
[{"$value":3,"$key":"fitges1"}]
score: undefined
[{"$value":3,"$key":"fitges1"},{"$value":3,"$key":"fitges2"}]
score: undefined
[{"$value":3,"$key":"fitges1"},{"$value":3,"$key":"fitges2"},{"$value":3,"$key":"fitges3"}]
score: undefined
答案 0 :(得分:2)
您的示例输出显示以下数据:
{
"bmzi-answers": {
"cat": {
"cat1": 3,
"cat2": 3,
"cat3": 3
}
}
}
您的查询使用orderByKey
和equalTo
来获取发出数组的可观察列表。如果密钥存在,查询将只返回包含单个对象的数组。将密钥合并到查询的路径中会更简单,如下所示:
let res = this._dbref.database.list(`/bmzi-answers/${id}`);
此查询返回的observable将是一个包含键的子项的数组(以AngularFire方式表示):
[
{ "$key": "cat1", "$value": 3 },
{ "$key": "cat2", "$value": 3 },
{ "$key": "cat3", "$value": 3 }
]
RxJS map
运算符可用于将发出的数组转换为另一个值,并且可以使用您所熟悉的Array.proptype
函数执行转换:
let id = "cat";
let regExp = new RegExp(`${id}\\d+`);
let res = this._dbref.database
.list(`/bmzi-answers/${id}`)
.map((array) => array
.filter((element) => regExp.test(element.$key))
.reduce((acc, element) => acc + element.$value, 0)
);
如果所有孩子都有cat
前缀,则不需要filter
,但您的问题并不清楚是否属于这种情况。
答案 1 :(得分:1)
流会发出数据。可观察的是一个流。
例如:
let stream = Rx.Observable.from([3,6,9])
此代码创建一个可观察的流,然后发出3然后6然后9
现在假设我们想要将这些值加倍:
let stream = Rx.Observable.from([3,6,9]).map((value) => {return value*2})
现在流发出6,12,18。
最后我们可以做到:
let stream1 = Rx.Observable.from([3,6,9])
let stream2 = stream1.map((value) => {return value*2})
现在我们可以订阅stream1或stream2或两者。
PS .reduce()
函数也可以与es5 Array.reduce
函数相同。您可以使用Arrays对流进行相同的操作。
数组是内存序列。流是一段时间的序列。
这就是我们可以轻松地将数组转换为流的原因。我们可以在每个发射之间放置间隔。等