Dart/Flutter中如何从列表中移除符合指定属性条件的对象
问题原因
你当前写法的核心问题是:Dart中List.contains、List.remove默认判断的是对象引用相等,你每次调用{teacherId, index}都会创建一个新的Set实例,哪怕值和列表中已存的元素完全一致,也会因为不是同一个对象实例判定为不匹配,所以逻辑永远走不到删除分支。
解决方案
方案1:直接遍历匹配值(无需修改现有存储结构)
用indexWhere方法遍历列表匹配两个属性的值,找到对应下标后直接移除:
void addTeacher(int teacherId, int index) { // 查找匹配元素的下标,匹配成功返回>=0的下标,失败返回-1 final matchIndex = selectedList.indexWhere((item) => item.contains(teacherId) && item.contains(index) ); if (matchIndex != -1) { selectedList.removeAt(matchIndex); myColor = Colors.grey; print('removed teacher => $teacherId'); } else { selectedList.add({teacherId, index}); myColor = AsasColors().blue; print('added teacher => $teacherId'); } notifyListeners(); print(selectedList); }
注意:你当前用
{teacherId, index}存储的是Set类型,是无序无重复的集合,如果要明确存储带字段名的结构化数据,更推荐用Map格式{'teacherId': teacherId, 'index': index},对应的匹配逻辑改为:final matchIndex = selectedList.indexWhere((item) => item['teacherId'] == teacherId && item['index'] == index );
方案2:自定义类(更规范的生产环境写法)
定义专门的实体类,重写==运算符和hashCode,之后就可以直接用contains、remove方法进行值匹配,代码更易维护:
// 定义实体类 class TeacherItem { final int teacherId; final int index; TeacherItem({required this.teacherId, required this.index}); // 重写相等判断逻辑,只要id和index都相等就判定为同一个对象 @override bool operator ==(Object other) => identical(this, other) || other is TeacherItem && runtimeType == other.runtimeType && teacherId == other.teacherId && index == other.index; @override int get hashCode => teacherId.hashCode ^ index.hashCode; }
修改后的业务逻辑代码:
// selectedList的类型改为List<TeacherItem> void addTeacher(int teacherId, int index) { final target = TeacherItem(teacherId: teacherId, index: index); if (selectedList.contains(target)) { selectedList.remove(target); myColor = Colors.grey; print('removed teacher => $teacherId'); } else { selectedList.add(target); myColor = AsasColors().blue; print('added teacher => $teacherId'); } notifyListeners(); print(selectedList); }
内容的提问来源于stack exchange,提问作者Faris Shomali
相关产品推荐
相关产品推荐

