如何检查对象是不是已存在于列表中
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如果使用这两个属性是可维护的,您可以:
bool alreadyExists = myList.Any(x=> x.Foo=="ooo" && x.Bar == "bat");
【讨论】:
仅来自 .Net 5 +【参考方案4】:您确定在这种情况下需要一份清单吗?如果您在列表中填充了许多项目,myList.Contains
或 myList.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
实现;您可以在类本身中覆盖 GetHashCode
和 Equals
。
【讨论】:
是的,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
【讨论】:
以上是关于如何检查对象是不是已存在于列表中的主要内容,如果未能解决你的问题,请参考以下文章
如何使用angularfire2检查孩子是不是存在于firebase列表中