如何检查对象是不是已存在于列表中

Posted

技术标签:

【中文标题】如何检查对象是不是已存在于列表中【英文标题】:how to check if object already exists in a list如何检查对象是否已存在于列表中 【发布时间】:2010-08-08 16:28:02 【问题描述】:

我有一个清单

  List<MyObject> myList

我正在将项目添加到列表中,并且我想检查该对象是否已经在列表中。

所以在我这样做之前:

 myList.Add(nextObject);

我想看看 nextObject 是否已经在列表中。

对象“MyObject”有许多属性,但比较是基于两个属性的匹配。

在我将新的“MyObject”添加到“MyObject”列表之前,最好的检查方法是什么。

我想到的唯一解决方案是从列表更改为字典,然后将键设为属性的串联字符串(这似乎有点不雅)。

任何其他使用列表或 LINQ 或其他东西的更清洁的解决方案?

【问题讨论】:

【参考方案1】:

这取决于具体情况的需要。例如,字典方法会很好假设:

    列表相对稳定(插入/删除不是很多,字典没有针对哪些优化) 列表非常大(否则字典的开销毫无意义)。

如果上述情况不适合您的情况,请使用方法Any():

Item wonderIfItsPresent = ...
bool containsItem = myList.Any(item => item.UniqueProperty == wonderIfItsPresent.UniqueProperty);

这将遍历列表,直到找到匹配项,或者直到它到达末尾。

【讨论】:

为 list.exists 使用谓词委托是另一种解决方案,见下文,但如果您有巨大的列表并且使用字典的键值会更快,因为它是一个哈希表!享受 如何检查多个值? 此解决方案仅适用于 .NET 5.0+ 。遗憾的是,我们中的一些人没有这个版本。 :-(【参考方案2】:

只需使用Contains 方法。请注意,它基于相等函数Equals

bool alreadyExist = list.Contains(item);

【讨论】:

这对我不起作用,它总是说它不存在 @Si8 如果您尝试比较对象,则必须确保 IEquatable.Equals 实现针对您的对象类型正确实现。否则,您将不会比较对象内容。有关如何实现此功能的示例,请参阅 Ahmad 指示的包含链接。 list.countains 不能在这里使用,因为它会为 dev1、dev11、dev111... 等报告 true @FranckE - 听起来您没有正确设置 IEquatable 来检查包含的内容。 当它是一个对象列表时不起作用,但它是一个字符串列表时起作用【参考方案3】:

如果使用这两个属性是可维护的,您可以:

bool alreadyExists = myList.Any(x=> x.Foo=="ooo" && x.Bar == "bat");

【讨论】:

仅来自 .Net 5 +【参考方案4】:

您确定在这种情况下需要一份清单吗?如果您在列表中填充了许多项目,myList.ContainsmyList.Any 会影响性能;运行时间将是二次的。您可能需要考虑使用更好的数据结构。例如,

 public class MyClass
    
        public string Property1  get; set; 
        public string Property2  get; set; 

    

    public class MyClassComparer : EqualityComparer<MyClass>
    
        public override bool Equals(MyClass x, MyClass y)
        
            if(x == null || y == null)
               return x == y;

            return x.Property1 == y.Property1 && x.Property2 == y.Property2;
        

        public override int GetHashCode(MyClass obj)
        
            return obj == null ? 0 : (obj.Property1.GetHashCode() ^ obj.Property2.GetHashCode());
        
    

您可以通过以下方式使用 HashSet:

  var set = new HashSet<MyClass>(new MyClassComparer());
  foreach(var myClass in ...)
     set.Add(myClass);

当然,如果MyClass 的相等定义是“通用的”,你就不需要编写IEqualityComparer 实现;您可以在类本身中覆盖 GetHashCodeEquals

【讨论】:

是的,V 的 bool 是我最喜欢的。就此而言,不久前(嗯,大约 3 周)我无法使用 HashSet,因为我正在编写 2.0 代码,我放弃了 HashSet 的 Mono 实现,因为它非常有用:) 【参考方案5】:

另外一点要提的是,你应该确保你的相等函数是你所期望的。您应该重写 equals 方法来设置对象的哪些属性必须匹配才能使两个实例被视为相等。

那你就可以了 mylist.contains(item)

【讨论】:

【参考方案6】:

这是一个快速控制台应用程序,用于描述如何解决您的问题的概念。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication3

    public class myobj
    
        private string a = string.Empty;
        private string b = string.Empty;

        public myobj(string a, string b)
        
            this.a = a;
            this.b = b;
        

        public string A
        
            get
            
                return a;
            
        

        public string B
        
            get
            
                return b;
            
        
    


    class Program
    
        static void Main(string[] args)
        
            List<myobj> list = new List<myobj>();
            myobj[] objects =  new myobj("a", "b"), new myobj("c", "d"), new myobj("a", "b") ;


            for (int i = 0; i < objects.Length; i++)
            
                if (!list.Exists((delegate(myobj x)  return (string.Equals(x.A, objects[i].A) && string.Equals(x.B, objects[i].B)) ? true : false; )))
                
                    list.Add(objects[i]);
                
            
        
    

享受吧!

【讨论】:

【参考方案7】:

编辑:我先说:


字典解决方案有什么不雅之处?这对我来说似乎非常优雅,尤其是因为您只需要在创建字典时设置比较器。


当然,当它也是值时,将它用作键是不雅的。

因此我会使用 HashSet。如果以后的操作需要索引,我会在添加完成后从中创建一个列表,否则,只需使用哈希集。

【讨论】:

我只会在对象列表很大时使用它,因为它是一个哈希表,并且它们非常适合快速查找。【参考方案8】:

简单但有效

MyList.Remove(nextObject)
MyList.Add(nextObject)

 if (!MyList.Contains(nextObject))
    MyList.Add(nextObject);

【讨论】:

【参考方案9】:

集合可以用作字典,不同之处在于您不需要引用 Microsoft Scripting Runtime 或使用后期绑定。请注意,在这种情况下,键必须是字符串。在我的情况下,键(数字)是整数,但声明为字符串。 您可以创建一个自定义布尔函数来检查该键是否存在于列表中。 ExcelMacroMastery.com 上的 Paul Kelly 有一篇好文章

' Function to check if item in the collection already exists
Function Exists(coll As Collection, key As String) As Boolean

    On Error GoTo EH

    IsObject (coll.Item(key))
    Exists = True

EH:
End Function

你可以这样使用它

For i = 3 To lastRow
    
        ' Ignore the Normal areas
        If rg.Cells(i, 1).value <> "Normal" Then
        
            number = rg.Cells(i, 1).value
            
            ' Check if the area exist in the collection using a custom function Exists
            If Exists(coll, number) = False Then
            
                Set oRiskArea = New clsHighRiskArea
                oRiskArea.number = number
                coll.add key:=oRiskArea.number, Item:=oRiskArea
                
            Else
                Set oRiskArea = coll(number)
            End If
            
            With oRiskArea
        
                .name = rg.Cells(i, 2).value
        
            End With
            
        End If

    Next i

【讨论】:

以上是关于如何检查对象是不是已存在于列表中的主要内容,如果未能解决你的问题,请参考以下文章

如何检查某个数据是不是已存在于firestore中

如何使用angularfire2检查孩子是不是存在于firebase列表中

如何在更新期间检查该数据是不是已存在于数据库中(Mongoose And Express)

检查列表框中的项目是不是已存在于许多其他列表框中?

如何检查列表中是不是存在列表项[关闭]

如何检查 AWS S3 中是不是已存在存储桶