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

Dart中如何移除列表中首个匹配特定属性的对象?

问题

根据Dart/Flutter文档,List.remove()可以移除列表中首个匹配的元素,removeWhere()也可用于移除对象。我尝试编写代码移除列表中首个属性匹配特定对象的元素,但调用testList.remove(z)返回false,目标对象未被移除;直接移除原对象a却能成功。以下是我的代码及运行输出:

代码示例

class Test {
  bool? a;
  bool? b;
  String? ex;
  String? yz;
  
  Test({
    this.a,
    this.b,
    this.ex,
    this.yz,
  });
  
   Map<String, dynamic> toJson() =>
      {
        "a": a,
        "b": b,
        "ex": ex,
        "yz": yz,
      };
  
  Test copy({bool? a, bool? b, String? ex, String? yz}){
    return Test(
      a : a ?? this.a,
      b : b ?? this.b,
      ex : ex ?? this.ex,
      yz : yz ?? this.yz,
    );
  }
}

void main() {
  Test a = Test(
    a : true,
    b : false,
    ex : "S001",
    yz : "plus"
  );
  
  Test b = Test(
    a : false,
    b : true,
    ex : "S001",
    yz : "plus"
  );
  
  Test c = Test(
    a : true,
    b : true,
    ex : "S001",
    yz : "plus"
  );
  
  Test d = Test(
    a : false,
    b : false,
    ex : "S001",
    yz : "plus"
  );
  
  Test z = a.copy(); // 希望移除列表中属性与a匹配的对象
  
  List<Test> testList = [a, b, c, d];
  
  for(var item in testList){ print(item.toJson()); } // [a, b, c, d]
  
  var result = testList.remove(z);
  
  print(result);
  
  for(var item in testList){ print(item.toJson()); }
}

运行输出

{a: true, b: false, ex: S001, yz: plus}
{a: false, b: true, ex: S001, yz: plus}
{a: true, b: true, ex: S001, yz: plus}
{a: false, b: false, ex: S001, yz: plus}
false
{a: true, b: false, ex: S001, yz: plus}
{a: false, b: true, ex: S001, yz: plus}
{a: true, b: true, ex: S001, yz: plus}
{a: false, b: false, ex: S001, yz: plus}

请问哪里操作有误?或有其他方法可实现该需求?


原因分析

Dart中List.remove()默认用对象引用相等性(即==运算符默认比较内存地址)匹配元素。你通过a.copy()创建的z是全新对象,虽然属性和a完全一致,但它和列表中的a不是同一个内存引用,所以remove(z)找不到匹配项,返回false;直接移除a时,因为列表中存在该引用,所以能成功。

解决方法

1. 重写==运算符和hashCode

让Test类支持按属性值比较相等性,这样List.remove()就能识别属性相同的对象。修改后的Test类如下:

class Test {
  bool? a;
  bool? b;
  String? ex;
  String? yz;
  
  Test({
    this.a,
    this.b,
    this.ex,
    this.yz,
  });
  
  Map<String, dynamic> toJson() =>
      {
        "a": a,
        "b": b,
        "ex": ex,
        "yz": yz,
      };
  
  Test copy({bool? a, bool? b, String? ex, String? yz}){
    return Test(
      a : a ?? this.a,
      b : b ?? this.b,
      ex : ex ?? this.ex,
      yz : yz ?? this.yz,
    );
  }

  // 重写==运算符,按属性比较相等性
  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is Test &&
          runtimeType == other.runtimeType &&
          a == other.a &&
          b == other.b &&
          ex == other.ex &&
          yz == other.yz;

  // 重写hashCode,确保属性相等的对象hash值一致
  @override
  int get hashCode => Object.hash(a, b, ex, yz);
}

修改后再调用testList.remove(z)即可成功移除首个属性匹配的元素。

2. 使用indexWhere+removeAt精准移除首个匹配项

无需修改类的相等性逻辑,直接通过属性条件找到首个匹配元素的索引,再移除:

// 找到首个属性与a匹配的元素索引
int targetIndex = testList.indexWhere((item) => 
  item.a == a.a && 
  item.b == a.b && 
  item.ex == a.ex && 
  item.yz == a.yz
);
// 找到则移除
if (targetIndex != -1) {
  testList.removeAt(targetIndex);
}

3. 使用removeWhere(注意:会移除所有匹配元素)

如果需要移除所有属性匹配的元素,可直接用removeWhere:

testList.removeWhere((item) => 
  item.a == a.a && 
  item.b == a.b && 
  item.ex == a.ex && 
  item.yz == a.yz
);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 14:23:07