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

如何高效修改列表特定元素值并优化Flutter函数性能?

Flutter列表元素修改函数的优化方向

问题背景

我需要高效修改列表中特定元素的值,目前已编写Flutter函数findAndOperate,可对主列表内选中元素的price执行PLUS或MULTIPLICATION运算,功能符合预期,但作为新手,想了解该函数的优化方向。

测试代码

// ignore_for_file: public_member_api_docs, sort_constructors_first
import 'package:flutter_test/flutter_test.dart';

void main() {
  test(
    'find list item and apply math',
    () {
      final mockList = <Model>[
        Model(id: '1', name: 'Cortado', price: 12),
        Model(id: '2', name: 'Caffe Latte', price: 24),
        Model(id: '3', name: 'Americano', price: 48),
        Model(id: '4', name: 'Turkish Coffee', price: 96),
        Model(id: '5', name: 'Filter Coffee', price: 64),
        Model(id: '6', name: 'Flat White', price: 128),
      ];

      final selectItems = [mockList[0], mockList[3]];
      final result = findAndOperate(
        mainList: mockList,
        selectedList: selectItems,
        operations: Operations.PLUS,
        value: 40,
      );
      print(result);
    },
  );
}

List<Model> findAndOperate({
  required double value,
  required Operations operations,
  required List<Model> mainList,
  required List<Model> selectedList,
}) {
  for (final selectItem in selectedList) {
    for (final item in mainList) {
      if (item == selectItem) {
        final itemIndex = mainList.indexOf(item);
        switch (operations) {
          case Operations.PLUS:
            final changeItem =
                selectItem.copyWith(price: selectItem.price + value);
            mainList.removeAt(itemIndex);
            mainList.insert(itemIndex, changeItem);
          case Operations.MULTIPLICATION:
            final changeItem = selectItem.copyWith(
              price: selectItem.price + (selectItem.price * value),
            );
            mainList.removeAt(itemIndex);
            mainList.insert(itemIndex, changeItem);
        }
      }
    }
  }
  return mainList;
}

// ignore: constant_identifier_names
enum Operations { PLUS, MULTIPLICATION }

class Model {
  Model({required this.id, required this.name, required this.price});

  final String id;
  final String name;
  final double price;

  Model copyWith({
    String? id,
    String? name,
    double? price,
  }) {
    return Model(
      id: id ?? this.id,
      name: name ?? this.name,
      price: price ?? this.price,
    );
  }

  @override
  String toString() => 'MockModel(id: $id, name: $name, price: $price)';

  @override
  bool operator ==(covariant Model other) {
    if (identical(this, other)) return true;

    return other.id == id && other.name == name && other.price == price;
  }

  @override
  int get hashCode => id.hashCode ^ name.hashCode ^ price.hashCode;
}

运行结果

[MockModel(id: 1, name: Cortado, price: 52.0), MockModel(id: 2, name: Caffe Latte, price: 24.0), MockModel(id: 3, name: Americano, price: 48.0), MockModel(id: 4, name: Turkish Coffee, price: 136.0), MockModel(id: 5, name: Filter Coffee, price: 64.0), MockModel(id: 6, name: Flat White, price: 128.0)]


优化方向

1. 大幅提升性能:消除嵌套循环与冗余查找

当前代码用两层嵌套循环遍历选中列表和主列表,时间复杂度为O(n*m)(n为选中元素数,m为主列表长度),且找到匹配元素后又调用mainList.indexOf(item)做重复查找,完全没必要。

优化方案:先把选中元素的唯一标识id存入Set(实现O(1)查找),再遍历主列表一次完成所有修改,时间复杂度降至O(n+m):

List<Model> findAndOperate({
  required double value,
  required Operations operations,
  required List<Model> mainList,
  required List<Model> selectedList,
}) {
  final selectedIds = selectedList.map((e) => e.id).toSet();
  
  return mainList.map((item) {
    if (!selectedIds.contains(item.id)) return item;
    
    final newPrice = switch(operations) {
      Operations.PLUS => item.price + value,
      Operations.MULTIPLICATION => item.price * (1 + value), // 简化原公式:price + price*value = price*(1+value)
    };
    
    return item.copyWith(price: newPrice);
  }).toList();
}

2. 遵循不可变原则:避免修改原列表

当前函数直接对传入的mainList执行removeAt和insert操作,会导致原列表被意外修改,不符合Flutter偏好不可变数据的最佳实践,也容易引发难以追踪的状态bug。

优化后的代码通过map生成新列表,原列表保持不变,更安全,也适配Provider、Riverpod等状态管理框架的更新逻辑。

3. 简化运算逻辑:优化乘法公式

原乘法运算代码selectItem.price + (selectItem.price * value)可简化为selectItem.price * (1 + value),逻辑更清晰,计算效率一致。

4. 增强扩展性:用函数替代枚举(可选)

如果后续需要添加减法、除法等运算,每次修改枚举和switch会很繁琐。可以直接传入运算函数,让函数更灵活:

// 定义运算函数类型
typedef PriceOperation = double Function(double currentPrice, double value);

List<Model> findAndOperate({
  required double value,
  required PriceOperation operation,
  required List<Model> mainList,
  required List<Model> selectedList,
}) {
  final selectedIds = selectedList.map((e) => e.id).toSet();
  
  return mainList.map((item) {
    if (!selectedIds.contains(item.id)) return item;
    return item.copyWith(price: operation(item.price, value));
  }).toList();
}

// 使用示例
final addResult = findAndOperate(
  mainList: mockList,
  selectedList: selectItems,
  operation: (price, val) => price + val,
  value: 40,
);

final multiplyResult = findAndOperate(
  mainList: mockList,
  selectedList: selectItems,
  operation: (price, val) => price * (1 + val),
  value: 0.5,
);

5. 修复潜在匹配问题:用唯一ID判断元素

原代码用item == selectItem判断匹配,但Model的==运算符包含了price字段——如果选中元素的price已被修改,会出现匹配失败的问题。实际应该只用唯一标识id判断元素身份,和价格无关。

6. 添加边界处理(可选)

可以增加简单的边界检查,避免无意义操作:

List<Model> findAndOperate({
  required double value,
  required Operations operations,
  required List<Model> mainList,
  required List<Model> selectedList,
}) {
  // 空列表直接返回原列表副本
  if (mainList.isEmpty || selectedList.isEmpty) return List.from(mainList);
  
  // 其他逻辑...
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 03:40:54