noc*_*ier 1 .net c# vb.net generics list
我有两个类型为T的通用列表.两个列表包含相同的类型,我想根据列表2中列表1中不存在的项目创建第三个列表(或列表2的过滤版本)在每个项目的ID上.
每个列表都包含一个"Package"对象,该对象具有ID属性.
现在我使用For Each循环模拟代码,我知道这很糟糕(Big O是恒定的时间)所以我想要一种更有效的方法.
这个代码是按照项目要求的VB,但我更喜欢C# - 所以任何一个代码示例都适合我.
Private Sub RemoveStockPackagesFromSelection()
Dim p As Package
Dim packageList As List(Of Package) = New List(Of Package)
Dim stockPackageList As List(Of Package) = New List(Of Package)
Dim result As List(Of Package) = New List(Of Package)
' Fill list with User's Packages
For i As Integer = 0 To ListBox2.Items.Count - 1
p = New Package
p.Id = CInt(ListBox2.Items(i).Value)
p.Name = ListBox2.Items(i).Text
packageList.Add(p)
Next
' Fill list with Stock Packages to compare:
Dim ds As DataSet = DAL.GetStandardPackages()
For Each dr As DataRow In ds.Tables(0).Rows
p = New Package
p.Id = CInt(dr.Item("id"))
stockPackageList.Add(p)
Next
' Do Compare and Filter
For Each p1 As Package In packageList
For Each p2 As Package In stockPackageList
If Not p1.Id = p2.Id Then
result.Add(p2)
End If
Next
Next
' Here is our new trimmed list:
Response.Write(result.Count)
End Sub
Run Code Online (Sandbox Code Playgroud)
什么是一个漂亮而干净的LINQ或Lamda进行此过滤的方式?什么是我的方法的大O和拟议方法的大O(只是为了满足我的好奇心).
谢谢
LINQ除了方法
这是最干净的方式,正如Maxim和svick所建议的那样,但是需要一个等于ID的重写Equals方法,或者你必须提供一个比较器(参见svicks答案).
var result = stockPackageList.Except(packageList).ToList();
Run Code Online (Sandbox Code Playgroud)
资源 许多LINQ samles可以在msdn中找到,网址为:http://msdn.microsoft.com/en-us/vcsharp/aa336746
我将留下我的答案的初始部分以供参考:
蛮力方式:
var result = stockPackageList
.Where(x => packageList.All(package => x.Id != package.Id))
.ToList();
Run Code Online (Sandbox Code Playgroud)
应该做的伎俩.您只需将lambda语法翻译为vb.net即可.
此查询将过滤所有项目stockPackageList中不存在ID的所有项目packageList.
您可以反转查询:
var result = stockPackageList
.Where(x => packageList.Any(package => x.Id == package.Id) == false)
.ToList();
Run Code Online (Sandbox Code Playgroud)
该Any如果任何项目的查询将返回真packageList有一个匹配的ID.此查询应该运行得快一点,因为它不必遍历整个集合All.
使用Eqality:
如果您的包对象实现,IEquatable<Package>您可以缩短代码
var result = stockPackageList
.Where(x => packageList.Contains(x) == false)
.ToList();
Run Code Online (Sandbox Code Playgroud)
使用哈希集:
如果您想使用哈希集,您可以这样做
var hash = new HashSet<string>(packageList.Select(x=>x.Id));
var result = stockPackageList.Where(x => hash.Contains(x.Id) == false).ToList();
Run Code Online (Sandbox Code Playgroud)
正如费斯特和伊万丹尼洛夫指出的那样,当列表变大时,这节省了计算时间.
无法真正读懂你的VB代码,但如果你想让l2中的项目不在l1中 -
她是一个C#代码示例
public class SomeObject
{
public string ID { get; set; }
}
public class SomeObjectComparer : IEqualityComparer<SomeObject>
{
public bool Equals(SomeObject x, SomeObject y)
{
return x.ID == y.ID;
}
public int GetHashCode(SomeObject obj)
{
return obj.ID.GetHashCode();
}
}
class Program
{
static void Main(string[] args)
{
List<SomeObject> l1, l2;
// lists init ...
IEqualityComparer<SomeObject> comparer = new SomeObjectComparer();
List<SomeObject> l3 = l2.Except(l1, comparer).ToList();
}
}
Run Code Online (Sandbox Code Playgroud)