使用.Contains()匹配LINQ查询中<t>的属性的属性

时间:2015-10-21 22:06:53

标签: vb.net linq

寻求有关如何使用.Contains()的{​​{1}}方法执行LINQ查询的帮助,以基于属性获取第二个List(Of T)中未包含的元素第一个List(Of T)T的属性。

以下是我编写的一些示例代码,这个场景是虚构的,但概念仍然存在。

List(Of T)

3 个答案:

答案 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

AllFilesValidFiles的相同起始代码:

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作为您收到的相同结构的列表,这样您就可以进行属性与属性比较,使用ExceptContains

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

简单,快速和可读。

相关问题