替代“-Contains”比较值而不是参考
Alternative to "-Contains" that compares value instead of reference
我有一个文件对象列表,我想检查给定的文件对象是否出现在该列表中。 -Contains
运算符几乎就是我要找的东西,但 -Contains
似乎使用了非常严格的相等性测试,其中对象引用必须相同。是否有一些不那么严格的选择?我希望下面代码中的 $boolean
变量第二次和第一次都 return True
。
PS C:\Users\Public\Documents\temp> ls
Directory: C:\Users\Public\Documents\temp
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 14.08.2017 18.33 5 file1.txt
-a---- 14.08.2017 18.33 5 file2.txt
PS C:\Users\Public\Documents\temp> $files1 = Get-ChildItem .
PS C:\Users\Public\Documents\temp> $files2 = Get-ChildItem .
PS C:\Users\Public\Documents\temp> $file = $files1[1]
PS C:\Users\Public\Documents\temp> $boolean = $files1 -Contains $file
PS C:\Users\Public\Documents\temp> $boolean
True
PS C:\Users\Public\Documents\temp> $boolean = $files2 -Contains $file
PS C:\Users\Public\Documents\temp> $boolean
False
PS C:\Users\Public\Documents\temp>
Get-ChildItem
returns 类型的对象 [System.IO.FileInfo]
.
Get-ChildItem C:\temp\test.txt | Get-Member | Select-Object TypeName -Unique
TypeName
--------
System.IO.FileInfo
正如评论中提到的 PetSerAl [System.IO.FileInfo]
没有实现 IComparable 或 IEquatable。
[System.IO.FileInfo].GetInterfaces()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False ISerializable
如果没有这些,正如您所注意到的,PowerShell 将仅支持引用相等性。 Lee Holmes 的作品很棒 blog post on this.
对此的解决方案是对具有可比性的子属性进行比较。您可以选择一个独特的特定 属性,例如 Mathias R Jessen 提到的 Fullname
。缺点是如果其他属性不同,则不会对其进行评估。
'a' | Out-File .\file1.txt
$files = Get-ChildItem .
'b' | Out-File .\file1.txt
$file = Get-ChildItem .\file1.txt
$files.fullname -Contains $file.fullname
True
或者,您可以使用 Compare-Object
cmdlet,它将比较两个对象之间的所有属性(或您使用 -Property
选择的特定属性)。
使用 Compare-Object
的 -IncludeEqual -ExcludeDifferent
标志,我们可以找到所有具有匹配属性的对象。然后,当数组被转换为 [bool]
时,如果它非空则为 $True
,如果为空则为 $False
。
'a' | Out-File .\file1.txt
$files = Get-ChildItem .
$file = Get-ChildItem .\file1.txt
[bool](Compare-Object $files $file -IncludeEqual -ExcludeDifferent)
True
'a' | Out-File .\file1.txt
$files = Get-ChildItem .
'b' | Out-File .\file1.txt
$file = Get-ChildItem .\file1.txt
[bool](Compare-Object $files $file -IncludeEqual -ExcludeDifferent)
False
Compare-Object
可能会占用大量资源,因此最好尽可能使用其他形式的比较。
我有一个文件对象列表,我想检查给定的文件对象是否出现在该列表中。 -Contains
运算符几乎就是我要找的东西,但 -Contains
似乎使用了非常严格的相等性测试,其中对象引用必须相同。是否有一些不那么严格的选择?我希望下面代码中的 $boolean
变量第二次和第一次都 return True
。
PS C:\Users\Public\Documents\temp> ls
Directory: C:\Users\Public\Documents\temp
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 14.08.2017 18.33 5 file1.txt
-a---- 14.08.2017 18.33 5 file2.txt
PS C:\Users\Public\Documents\temp> $files1 = Get-ChildItem .
PS C:\Users\Public\Documents\temp> $files2 = Get-ChildItem .
PS C:\Users\Public\Documents\temp> $file = $files1[1]
PS C:\Users\Public\Documents\temp> $boolean = $files1 -Contains $file
PS C:\Users\Public\Documents\temp> $boolean
True
PS C:\Users\Public\Documents\temp> $boolean = $files2 -Contains $file
PS C:\Users\Public\Documents\temp> $boolean
False
PS C:\Users\Public\Documents\temp>
Get-ChildItem
returns 类型的对象 [System.IO.FileInfo]
.
Get-ChildItem C:\temp\test.txt | Get-Member | Select-Object TypeName -Unique
TypeName
--------
System.IO.FileInfo
正如评论中提到的 PetSerAl [System.IO.FileInfo]
没有实现 IComparable 或 IEquatable。
[System.IO.FileInfo].GetInterfaces()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False ISerializable
如果没有这些,正如您所注意到的,PowerShell 将仅支持引用相等性。 Lee Holmes 的作品很棒 blog post on this.
对此的解决方案是对具有可比性的子属性进行比较。您可以选择一个独特的特定 属性,例如 Mathias R Jessen 提到的 Fullname
。缺点是如果其他属性不同,则不会对其进行评估。
'a' | Out-File .\file1.txt
$files = Get-ChildItem .
'b' | Out-File .\file1.txt
$file = Get-ChildItem .\file1.txt
$files.fullname -Contains $file.fullname
True
或者,您可以使用 Compare-Object
cmdlet,它将比较两个对象之间的所有属性(或您使用 -Property
选择的特定属性)。
使用 Compare-Object
的 -IncludeEqual -ExcludeDifferent
标志,我们可以找到所有具有匹配属性的对象。然后,当数组被转换为 [bool]
时,如果它非空则为 $True
,如果为空则为 $False
。
'a' | Out-File .\file1.txt
$files = Get-ChildItem .
$file = Get-ChildItem .\file1.txt
[bool](Compare-Object $files $file -IncludeEqual -ExcludeDifferent)
True
'a' | Out-File .\file1.txt
$files = Get-ChildItem .
'b' | Out-File .\file1.txt
$file = Get-ChildItem .\file1.txt
[bool](Compare-Object $files $file -IncludeEqual -ExcludeDifferent)
False
Compare-Object
可能会占用大量资源,因此最好尽可能使用其他形式的比较。