Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vb.net 使用.Contains()匹配<;属性的属性;T>;在LINQ查询中_Vb.net_Linq - Fatal编程技术网

Vb.net 使用.Contains()匹配<;属性的属性;T>;在LINQ查询中

Vb.net 使用.Contains()匹配<;属性的属性;T>;在LINQ查询中,vb.net,linq,Vb.net,Linq,正在寻找有关如何使用列表(of T)的.Contains()方法执行LINQ查询的帮助,以基于第一个列表(of T)中的T属性返回第二个列表(of T)中未包含的元素 下面是我编写的一些示例代码,这个场景是虚构的,但概念仍然存在 Module Module1 Sub Main() ' Get all Files in a directory that contain `.mp` in the name Dim AllFiles As List(Of IO

正在寻找有关如何使用
列表(of T)
.Contains()
方法执行LINQ查询的帮助,以基于第一个
列表(of T)
中的
T
属性返回第二个
列表(of T)
中未包含的元素

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

Module Module1

    Sub Main()
        ' Get all Files in a directory that contain `.mp` in the name
        Dim AllFiles As List(Of IO.FileInfo) = New IO.DirectoryInfo("C:\Test\Path").GetFiles("*.mp*").ToList
        Dim ValidFiles As New List(Of fileStruct)

        ' Get all Files that actually have an extension of `.mp3`
        AllFiles.ForEach(Sub(x) If x.Extension.Contains("mp3") Then ValidFiles.Add(New fileStruct(prop1:=x.Name, path:=x.FullName)))

        ' Attempting the get all files that are not listed in the Valid files list
        Dim InvalidFiles As IO.FileInfo() = From file As IO.FileInfo In AllFiles Where Not ValidFiles.Contains(Function(x As fileStruct) x.fleInfo.FullName = file.FullName) Select file
        ' Errors on the `.Contains()` method because I have no idea what I'm doing and I am basically guessing at this point

        'Here is the same but instead using the `.Any()` Method
        Dim InvalidFiles As IO.FileInfo() = From file As IO.FileInfo In AllFiles Where Not ValidFiles.Any(Function(x As fileStruct) x.fleInfo.FullName = file.FullName) Select file
        ' This doesn't error out, but all files are returned
    End Sub

    Public Structure fileStruct
        Private _filePath As String
        Private _property1 As String

        Public ReadOnly Property property1 As String
            Get
                Return _property1
            End Get
        End Property

        Public ReadOnly Property fleInfo As IO.FileInfo
            Get
                Return New IO.FileInfo(_filePath)
            End Get
        End Property

        Public Sub New(ByVal prop1 As String, ByVal path As String)
            _property1 = prop1
            _filePath = path
        End Sub
    End Structure
End Module

正如其他人所指出的,.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
List list1=新列表{1,2,3};
List list2=新列表{3,4,5};
List list3=list1.Where(list1value=>!list2.Contains(list1value)).ToList();//1, 2
以这里的注释为例,使用不同的类型。此查询使用.Any()

List list1=新列表{…};
List list2=新列表{…};
List list3=list1.Where(product=>!list2.Any(vendor=>product.VendorID==vendor.ID)).ToList();
//清单3将包含供应商ID与清单2中任何供应商ID不匹配的产品。

这或多或少是问题中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()
这与Sam的答案基本相同,只是您的文件/mp3使用情况不同。所有文件有809项,有效文件有274项。生成的无效列表为535


现在,让我们将其加速50-60倍:

所有文件和有效文件的起始代码相同:

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()
使用
秒表
,结果如下:

调用
IsValid
函数的普通For/Each循环也会得到类似的结果


如果您不需要其他
文件信息
,您可以将您的
所有文件
创建为与接收到的文件结构相同的列表,以便进行属性与属性的比较,使用
除了
包含

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()
这也允许您使用
,但
更简单、更快:

invalid2 = AllFiles2.Except(ValidFiles).ToList()

即使您需要FileInfo中的其他项目,只要使用文件名,您也可以轻松获取它们,除非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

简单、快速、易读。

如果您试图获得两个列表之间的差异,请不要使用
Contains()
,使用
Except()
@CraigW-
.Except()
方法正在寻找与第一个相同类型的第二个集合。在我的例子中,集合不是同一类型的。以您的示例为例,我需要匹配的是
list1value.someProperty.value
list2
,但仍然有所有文件的多次迭代(有效文件一次,无效文件一次)否。如果每个文件都在有效文件中,则所有文件都会迭代一次测试。这至少会导致有效文件的部分迭代,但结果是无效的(文件)。a for/Each循环和Where and anon lambda的IL代码基本上与Steely Dan的LPlus One相同。绝对属于有效文件列表。此外,如果您想真正加快速度,请使用哈希集。实际上,3-4毫秒的速度和它看起来的一样快。ValidFiles的Hashset将Where/Contains的速度从74提高到4ms,但它比其他一些Hashset的速度要慢(只慢一点点)。OP的问题可能是使用哈希集,因为它来自其他地方。我从COM对象收到结构中返回的有效文件列表,然后我需要将这些文件与目录中的文件进行比较,我需要的是所有文件与COM对象返回的文件之间的差异
 Where/Contains count: 535, time: 74ms  
         Except count: 535, time: 3ms
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