You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于Observable返回的实验数据计算各实验通过用户的平均尝试次数

问题解答

是否可以通过简单subscribe实现

完全可以实现,直接在subscribe的next回调中完成过滤、分组、均值计算逻辑即可,示例代码如下:

// 假设experimentalResult$为你的源Observable,一次性发射所有用户的实验结果数组
experimentalResult$.subscribe({
  next: (allUserResults: experimentalresult[]) => {
    // 初始化分组容器:key为实验项,value存储该组总尝试次数、通过人数
    const expGroup = new Map<Task, { totalAttempts: number, passCount: number }>();

    // 遍历所有用户的所有实验记录
    allUserResults.forEach(userResult => {
      userResult.Results.forEach(expRecord => {
        // 仅统计实验通过的记录
        if (!expRecord.Status) return;
        // 该实验首次统计时初始化分组
        if (!expGroup.has(expRecord.Experiment)) {
          expGroup.set(expRecord.Experiment, { totalAttempts: 0, passCount: 0 });
        }
        const currentGroup = expGroup.get(expRecord.Experiment)!;
        currentGroup.totalAttempts += expRecord.Attempts;
        currentGroup.passCount += 1;
      });
    });

    // 按实验顺序生成平均结果数组,此处如果有固定实验排序规则,可先对expGroup的key做排序再遍历
    const result = Array.from(expGroup.values()).map(group => {
      return (group.totalAttempts / group.passCount).toFixed(1);
    });

    // 此处result就是你需要的格式,比如['2.7', '3.4', '2.1']
    console.log(result);
  },
  error: (err) => console.error('数据处理失败:', err)
})

这种写法适合一次性使用的场景,缺点是逻辑耦合在订阅回调中,不方便复用,也难以和其他RxJS流逻辑组合。

更推荐的实现方案

建议使用RxJS操作符把处理逻辑封装在流中,后续可以直接复用处理后的流,也方便扩展其他逻辑:

import { map } from 'rxjs';

// 把数据处理逻辑放在pipe里,和订阅逻辑分离
const experimentAvg$ = experimentalResult$.pipe(
  map((allUserResults: experimentalresult[]) => {
    const expGroup = new Map<Task, { totalAttempts: number, passCount: number }>();
    allUserResults.forEach(userResult => {
      userResult.Results.forEach(expRecord => {
        if (!expRecord.Status) return;
        if (!expGroup.has(expRecord.Experiment)) {
          expGroup.set(expRecord.Experiment, { totalAttempts: 0, passCount: 0 });
        }
        const currentGroup = expGroup.get(expRecord.Experiment)!;
        currentGroup.totalAttempts += expRecord.Attempts;
        currentGroup.passCount += 1;
      });
    });
    // 如果需要固定实验顺序,比如按预设的实验列表排序,可替换为以下逻辑:
    // const fixedExpOrder = [Task.EXP1, Task.EXP2, Task.EXP3];
    // return fixedExpOrder.map(exp => {
    //   const group = expGroup.get(exp);
    //   return group ? (group.totalAttempts / group.passCount).toFixed(1) : '0';
    // });
    return Array.from(expGroup.values()).map(group => (group.totalAttempts / group.passCount).toFixed(1));
  })
);

// 订阅时直接拿到处理完成的结果
experimentAvg$.subscribe(result => console.log(result));

如果你的源Observable是逐个发射单用户的experimentalresult数据,而非一次性发射全量数组,把上述的map替换为scan操作符做累加即可,逻辑完全一致。

内容的提问来源于stack exchange,提问作者user16853055

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 22:06:01