Flutter/Dart 如何按列表元素属性合并并执行对应汇总操作
Dart/Flutter 食材用量合并实现方案
实现思路
- 对原始列表按
name属性分组,将同名称的食材归为一组 - 每组内再按
unit属性二次分组,相同单位的用量累加 - 将同组内不同单位的用量字符串用
+拼接,生成最终的total字段 - 整理成要求的输出结构即可
完整代码实现
1. 定义数据模型(可选,也可直接用Map操作)
class Ingredient { final String name; final String quantity; final String unit; Ingredient({ required this.name, required this.quantity, required this.unit, }); // 从Map创建对象 factory Ingredient.fromMap(Map<String, String> map) { return Ingredient( name: map['name']!, quantity: map['quantity']!, unit: map['unit']!, ); } } // 输出结构的模型 class MergedIngredient { final String name; final String total; MergedIngredient({required this.name, required this.total}); // 转成Map输出 Map<String, String> toMap() { return { 'name': name, 'total': total, }; } }
2. 核心处理逻辑
void main() { // 原始测试数据 final List<Map<String, String>> rawList = [ {"name": 'olive oil', "quantity": "1", "unit": "spoons"}, {"name": 'olive oil', "quantity": "2", "unit": "spoons"}, {"name": 'parmesan cheese', "quantity": "20", "unit": "slices"}, {"name": 'parmesan cheese', "quantity": "3/4", "unit": "cup"}, {"name": 'salt', "quantity": "1", "unit": "teaspoon"}, ]; // 转成模型列表操作 final List<Ingredient> ingredients = rawList.map((e) => Ingredient.fromMap(e)).toList(); // 第一步:按name分组 final Map<String, List<Ingredient>> nameGroups = {}; for (var ing in ingredients) { if (!nameGroups.containsKey(ing.name)) { nameGroups[ing.name] = []; } nameGroups[ing.name]!.add(ing); } // 第二步:处理每一组的用量 final List<MergedIngredient> mergedList = []; nameGroups.forEach((name, ingList) { // 按unit二次分组,统计同单位总用量 final Map<String, num> unitQuantityMap = {}; // 存无法直接计算的分数用量(示例里的3/4这种) final List<String> specialUnits = []; for (var ing in ingList) { // 尝试把用量转成数值计算,转失败的直接拼接 final num? quantity = num.tryParse(ing.quantity); if (quantity != null) { unitQuantityMap[ing.unit] = (unitQuantityMap[ing.unit] ?? 0) + quantity; } else { specialUnits.add("${ing.quantity} ${ing.unit}"); } } // 拼接所有用量 final List<String> totalParts = []; unitQuantityMap.forEach((unit, totalQty) { totalParts.add("$totalQty $unit"); }); totalParts.addAll(specialUnits); mergedList.add(MergedIngredient( name: name, total: totalParts.join(" + "), )); }); // 输出结果 final output = mergedList.map((e) => e.toMap()).toList(); print(output); }
运行输出
运行后输出的结果和预期完全一致:
[ {name: olive oil, total: 3 spoons}, {name: parmesan cheese, total: 20 slices + 3/4 cup}, {name: salt, total: 1 teaspoon} ]
扩展说明
如果需要支持分数的运算(比如同单位的1/2和1/4相加得到3/4),可以引入第三方库处理分数的解析和计算,替换掉现有代码里的数值解析逻辑即可。
内容的提问来源于stack exchange,提问作者Rod
相关产品推荐
相关产品推荐

