寻求有关如何使用.Contains()
的{{1}}方法执行LINQ查询的帮助,以基于属性获取第二个List(Of T)
中未包含的元素第一个List(Of T)
中T
的属性。
以下是我编写的一些示例代码,这个场景是虚构的,但概念仍然存在。
List(Of T)
答案 0 :(得分:1)
这是问题中或多或少直接实现MP3文件列表。我确实使用了FileItem
类而不是结构。好的部分是事后:
' note: EnumerateFiles
Dim AllFiles As List(Of IO.FileInfo) = New IO.DirectoryInfo("M:\Music").
EnumerateFiles("*.mp*", IO.SearchOption.AllDirectories).ToList()
Dim goofyFilter As String() = {"g", "h", "s", "a"}
' filter All files to those starting with the above (lots of
' Aerosmith, Steely Dan and Heart)
Dim ValidFiles As List(Of FileItem) = AllFiles.
Where(Function(w) goofyFilter.Contains((w.Name.ToLower)(0))).
Select(Function(s) New FileItem(s.FullName)).ToList()
Dim invalid As List(Of FileInfo)
invalid = AllFiles.Where(Function(w) Not ValidFiles.
Any(Function(a) w.FullName = a.FilePath)).ToList()
除了你的文件/ mp3使用情况之外,这与Sam的回答大致相同。 AllFiles有809个项目,ValidFiles有274.产生的无效列表是535.
现在,让加速50-60x :
AllFiles
和ValidFiles
的相同起始代码:
Dim FileItemValid = Function(s As String)
Dim valid As Boolean = False
For Each fi As FileItem In ValidFiles
If fi.FilePath = s Then
valid = True
Exit For
End If
Next
Return valid
End Function
invalid = AllFiles.Where(Function(w) FileItemValid(w.FullName) = False).ToList()
使用Stopwatch
,结果为:
Where/Any count: 535, time: 572ms FileItemValid count: 535, time: 9ms
使用调用IsValid
函数的普通旧For / Each循环得到类似的结果。
如果您不需要其他FileInfo
,您可以创建AllFiles
作为您收到的相同结构的列表,这样您就可以进行属性与属性比较,使用Except
和Contains
:
AllFiles2 = Directory.EnumerateFiles("M:\Music", "*.mp3", IO.SearchOption.AllDirectories).
Select(Function(s) New FileItem(s)).ToList()
现在,您可以将Contains
用于中等结果:
invalid2 = AllFiles2.Where(Function(w) Not ValidFiles.Contains(w)).ToList()
这也允许您使用更简单,更快捷的Except
:
invalid2 = AllFiles2.Except(ValidFiles).ToList()
Where/Contains count: 535, time: 74ms Except count: 535, time: 3ms
即使您需要FileInfo中的其他项目,也可以使用文件名
轻松获取它们答案 1 :(得分:0)
正如其他人所说,.Except()是一种更好的方法,但这里是你问题的答案:
List<int> list1 = new List<int> { 1, 2, 3 };
List<int> list2 = new List<int> { 3, 4, 5 };
List<int> list3 = list1.Where(list1value => !list2.Contains(list1value)).ToList(); // 1, 2
基于此处的评论作为使用不同类型的示例。此查询使用.Any()
List<Product> list1 = new List<Produc> { ... };
List<Vendor> list2 = new List<Vendor> { ... };
List<Product> list3 = list1.Where(product => !list2.Any(vendor => product.VendorID == vendor.ID)).ToList();
// list3 will contain products with a vendorID that does not match the ID of any vendor in list2.
答案 2 :(得分:0)
简单地使用除了CraigW建议的。你必须做一些预测(选择)才能完成它。
Dim InvalidFiles as IO.FileInfo() = AllFiles.Select(Function(p) p.FullName).Except(ValidFiles.Select(Function(x) x.fleInfo.FullName)).Select(Function(fullName) New IO.FileInfo(fullName)).ToArray()
注意:这段代码不是很有效,也不是很易读,但也很有用。
但我会选择这样的事情:
Dim AllFiles As List(Of IO.FileInfo) = New IO.DirectoryInfo("C:\MyFiles").GetFiles("*.mp*").ToList
Dim ValidFiles As New List(Of fileStruct)
Dim InvalidFiles as New List(Of FileInfo)
For Each fileInfo As FileInfo In AllFiles
If fileInfo.Extension.Contains("mp3") Then
ValidFiles.Add(New fileStruct(prop1:=fileInfo.Name, path:=fileInfo.FullName))
Else
InvalidFiles.Add(fileInfo)
End If
Next
简单,快速和可读。