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

Dart中如何实现类似SQL多字段GROUP BY的Map列表分组聚合?

Dart 实现多字段分组聚合求和

你可以直接通过给groupBy传入复合分组键的方式实现多字段分组,不需要额外引入其他工具,完整实现如下:

import 'package:collection/collection.dart';

void main() {
  var data = [
    {"day": 'Monday', "weather": 'warm', 'ctd': 20, 'other':'a'},
    {"day": 'Monday', "weather": 'warm', 'ctd': 15, 'other':'b'},
    {"day": 'Tuesday', "weather": 'cold', 'ctd': 25, 'other':'c'},
    {"day": 'Tuesday', "weather": 'cold', 'ctd': 35, 'other':'d'},
  ];

  // 以day和weather两个字段作为联合分组键
  final groupMap = groupBy(
    data,
    (Map item) => (item['day'], item['weather']),
  );

  // 对每个分组做ctd字段求和,再转换为目标列表结构
  final result = groupMap.entries.map((entry) {
    final (day, weather) = entry.key;
    final totalCtd = entry.value.fold<int>(
      0,
      (pre, cur) => pre + (cur['ctd'] as int),
    );
    return {
      "day": day,
      "weather": weather,
      "ctd": totalCtd,
    };
  }).toList();

  print(result);
  // 输出结果和预期完全一致:
  // [{day: Monday, weather: warm, ctd: 35}, {day: Tuesday, weather: cold, ctd: 60}]
}

低版本兼容说明

如果你的项目使用Dart 3.0以下版本,不支持Record(记录)语法,可以用拼接字符串作为复合分组键,写法如下:

final groupMap = groupBy(
  data,
  (Map item) => "${item['day']}||${item['weather']}",
);

final result = groupMap.entries.map((entry) {
  final keyParts = entry.key.split('||');
  final totalCtd = entry.value.fold<int>(
    0,
    (pre, cur) => pre + (cur['ctd'] as int),
  );
  return {
    "day": keyParts[0],
    "weather": keyParts[1],
    "ctd": totalCtd,
  };
}).toList();

注意拼接字符串时选择一个不会出现在分组字段值里的分隔符,避免键冲突。

原有写法问题说明

你之前的尝试存在两个问题:

  • 分组键仅传入了day单个字段,没有将weather纳入分组维度,无法区分同日期不同天气的分组
  • 聚合后直接返回了「分组键:ctd求和值」的Map结构,没有组装分组维度的字段,也没有转换为要求的List格式

如果后续需要增加分组字段,只需要在复合键里追加对应字段即可;如果需要实现计数、求平均值等其他聚合逻辑,修改fold内的计算规则就能实现。


内容的提问来源于stack exchange,提问作者José Luis Zarabanda Díaz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 06:27:24