То, как. NET по умолчанию сравнивает , все не так просто прощает , как PowerShell!
[array]::IndexOf($array, $reference)
будет go через массив и возвращает текущий индекс, когда он встречает элемент, для которого верно следующее:
$item.Equals($reference)
... что НЕ обязательно так же, как и при выполнении
$item -eq $reference
Для простых значений, таких как числа, даты и т. Д., Equals()
работает точно так же, как -eq
:
PS C:\> $a = 1
PS C:\> $b = 1
PS C:\> $a.Equals($b) # $true
... что является причиной Ваш первый пример работает как положено!
Для более сложных объектов Equals()
работает немного по-другому. Оба значения ДОЛЖНЫ относиться к одному и тому же объекту , недостаточно, чтобы они имели похожие или даже идентичные значения:
PS C:\> $a = New-Object object
PS C:\> $b = New-Object object
PS C:\> $a.Equals($b) # $false
В приведенном выше примере $a
и $b
похожи (если не идентичны ) - они оба являются пустыми объектами - но они не один и тот же объект .
Аналогично, если мы тестируем с вашими входными значениями они не равны :
PS C:\> $a = Get-Item "C:\"
PS C:\> $b = "C:\"
PS C:\> $a.Equals($b) # $false
Одна из причин, по которой их нельзя считать одинаковыми, как AdminOfThings превосходно объясняет , это несоответствие типов - но операторы сравнения PowerShell могут помочь нам в этом!
Вы заметите, что this работает:
PS C:\> $a = Get-Item "C:\"
PS C:\> $b = "C:\"
PS C:\> $b -eq $a
True
Это потому, что поведение -eq
зависит от левого операнда. В приведенном выше примере "C:\"
является строкой, поэтому PowerShell преобразует $a
в строку, и неожиданно сравнение становится больше похоже на "C:\".Equals("C:\")
!
Имея это в виду, вы можете создать Ваша собственная Find-IndexOf
функция для выполнения $reference -eq $item
(или любой другой механизм сравнения, который вы хотите) с помощью простого for()
l oop:
function Find-IndexOf
{
param(
[array]$Array,
[object]$Value
)
for($idx = 0; $idx -lt $Array.Length; $idx++){
if($Value -eq $Array[$idx]){
return $idx
}
}
return -1
}
Теперь вы сможете сделать :
PS C:\> $array = @('','PowerShell is case-insensitive by default')
PS C:\> $value = 'POWERsheLL iS cASe-InSenSItIVe BY deFAuLt'
PS C:\> Find-IndexOf -Array $array -Value $value
1
Или:
PS C:\> $array = Get-ChildItem C:\images
PS C:\> $value = 'C:\images\image123.png'
PS C:\> Find-IndexOf -Array $array -Value $value
5
Добавление сравнения к указанному свойству c для каждого из элементов массива (например, Name
файла в вашем примере), мы заканчиваем что-то вроде этого:
function Find-IndexOf
{
param(
[array]$Array,
[object]$Value,
[string]$Property
)
if($Property){
for($idx = 0; $idx -lt $Array.Length; $idx++){
if($Value -eq $Array[$idx].$Property){
return $idx
}
}
}
else {
for($idx = 0; $idx -lt $Array.Length; $idx++){
if($Value -eq $Array[$idx]){
return $idx
}
}
}
return -1
}
Find-IndexOf -Array @(Get-ChildItem C:\images) -Value image123.png -Property Name