有没有一种方法可以从对象列表中删除具有特定键值的对象的第一个实例?

huangapple go评论70阅读模式
英文:

Is there a way to remove the first instance of an Object with specific key values from a list of Objects

问题

Dart/Flutter文档提到使用removeremoveWhere是从对象列表中移除对象的正确方法。

这也在StackOverflow上有答案:

  1. Dart参考文档

    从列表中删除值的第一个出现。

    如果值在列表中,则返回true;否则返回false。列表必须是可增长的。

  2. DevSheet文章

    如果您想从列表中删除单个项目及其在列表中的第一次出现,那么可以使用List.remove()函数。它将搜索项目在列表中的第一个出现并删除它。remove()函数以项目作为参数并删除它。

  3. StackOverflow问题

  4. Flutter示例

    remove(element)从列表中删除单个与传递的元素严格相等的元素。

所以我编写了以下代码来尝试实现我心中的想法:

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()); }
}

然而,当我尝试实现时,remove函数返回false。我的结果是false,并且被问到的对象没有从列表中移除。尽管从列表中删除 'a' 的操作正常进行,但删除 a.copy() 却不起作用。

我是不是做错了什么,或者有没有一种不同的方法来从列表中删除所述对象?

我已将此代码添加到公共的DartPad中。是否有人可以帮助我理解为什么这不起作用以及如何获得期望的结果?

DartPad链接

{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}
英文:

The Dart/Flutter documentation mentions using remove and removeWhere as being the right way to remove objects from a list of objects.

This is also answered here on SO:

  1. Dart Reference

> Removes the first occurrence of value from this list.
>
> Returns true if value was in the list, false otherwise. The list must
> be growable.

  1. DevSheet Article

> If you want to delete a single item from the list with its first
> occurrence in the list then you can use the List.remove() function. It
> will search for the first occurrence of the item in the list and
> delete it. The remove() function takes the item as a parameter and
> deletes it.

  1. StackOverflow Question

  2. Flutter By Example

> remove(element) removes a single element from the list, which is
> strictly equal to the element passed in.

So I came up with the following code to try implement something I have in mind:

class Test {
  bool? a;
  bool? b;
  String? ex;
  String? yz;
  
  Test({
    this.a,
    this.b,
    this.ex,
    this.yz,
  });
  
   Map&lt;String, dynamic&gt; toJson() =&gt;
      {
        &quot;a&quot;: a,
        &quot;b&quot;: b,
        &quot;ex&quot;: ex,
        &quot;yz&quot;: 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 : &quot;S001&quot;,
    yz : &quot;plus&quot;
  );
  
  Test b = Test(
    a : false,
    b : true,
    ex : &quot;S001&quot;,
    yz : &quot;plus&quot;
  );
  
  Test c = Test(
    a : true,
    b : true,
    ex : &quot;S001&quot;,
    yz : &quot;plus&quot;
  );
  
  Test d = Test(
    a : false,
    b : false,
    ex : &quot;S001&quot;,
    yz : &quot;plus&quot;
  );
  
  Test z = a.copy(); // we want to remove an object with attributes matching &#39;a&#39; from the list
  
  List&lt;Test&gt; 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()); }
  
}

However when I try to implement this, the remove function returns false.
My result is a false, and the object in question is not removed from the list.
While removing 'a' from the list works just fine, removing a.copy() doesn't.

Am I doing something wrong or is there a different way to remove said object from the list?

I've added this code to a public dartpad. Can anyone help me understand why this isn't working and what can be done to obtain the desired result?

Dartpad link

{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}

答案1

得分: 0

我查看了答案,显然需要重写'=='运算符和hashCode函数,以便'remove'能够正确比较同一类的两个对象并从列表中删除对象。

@override
bool operator ==(other) {
    if (identical(this, other)) return true;
    return other is Test &&
        other.a == a &&
        other.b == b &&
        other.ex == ex &&
        other.yz == yz;
}

@override
int get hashCode => Object.hash(a, b, ex, yz);

现在'remove'功能正常了。取消注释'z'的那一行:

Test z = a.copy(); 
List<Test> testList = [a, b, c, d];
for(var item in testList){ print(item.toJson()); } // [a, b, c, d]

var result = testList.remove(z);  // 现在可以正常工作
// var result = testList.remove(a.copy()); // 也可以工作

print(result); // true 
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}
true
{a: false, b: true, ex: S001, yz: plus}
{a: true, b: true, ex: S001, yz: plus}
{a: false, b: false, ex: S001, yz: plus}
英文:

I looked around for the answer and apparently, I need to override the '==' operator and the hashCode functions so 'remove' can correctly compare two objects of the same class and remove the object from the list.

 @override
  bool operator ==(other) {
    if (identical(this, other)) return true;
    return other is Test &amp;&amp;
        other.a == a &amp;&amp;
        other.b == b &amp;&amp;
        other.ex == ex &amp;&amp;
        other.yz == yz;
  }
  
  @override
  int get hashCode =&gt; Object.hash(a, b, ex, yz);

Now the remove works. Uncommenting the line for 'z':

  Test z = a.copy(); 
  List&lt;Test&gt; testList = [a, b, c, d];
  for(var item in testList){ print(item.toJson()); } // [a, b, c, d]

  var result = testList.remove(z);  // works now
  // var result = testList.remove(a.copy()); // also works

  print(result); // true 
  for(var item in testList){ print(item.toJson()); }

yields the result:

{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}
true
{a: false, b: true, ex: S001, yz: plus}
{a: true, b: true, ex: S001, yz: plus}
{a: false, b: false, ex: S001, yz: plus}

huangapple
  • 本文由 发表于 2023年6月19日 04:29:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/76502427.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定