Powershell - Как определить с помощью переменной, индекс совпадающей строки в массиве - PullRequest
0 голосов
/ 17 февраля 2020
$array = @('blue','red','purple','pink')
$array2 = @('brown','red','black','yellow')

$array | ForEach-Object {
    if ($array2 -contains $_) {
        Write-Host "`$array2 contains the `$array1 string [$_]"
    }
}

как получить индекс строки совпадения?

Ответы [ 5 ]

3 голосов
/ 17 февраля 2020

Хотя операторы PowerShell -in / -contains позволяют проверять наличие данного значения в коллекции (является ли данное значение элементом коллекции), есть нет прямая поддержка для получения индекса элемента с использованием только собственных функций PowerShell .

Для . NET массивов (например, созданные в вашем вопросе [1] ) вы можете использовать их .IndexOf() экземпляр метод , в котором используется сравнение case-SENSITIVE на основе культуры current ; Например:

$array.IndexOf('red')  # -> 1; case-SENSITIVE, current-culture comparison

Обратите внимание, что сам PowerShell, как правило, нечувствителен к регистру, а для -eq (и в других контекстах) для сравнения используется культура инвариант .


A решение без учета случая на основе инварианта культуры с использованием типа массива stati c [Array]::FindIndex() method :

$array = 'blue', 'ReD', 'yellow'
[Array]::FindIndex($array, [Predicate[string]] { 'red' -eq $args[0] }) # -> 1

Обратите внимание, что путем делегирования блоку сценариев PowerShell ({ ... }), в котором каждый элемент ($args[0]) проверяется на соответствие целевому значению с помощью -eq вы неявно получаете нечувствительное к регистру, инвариантное к культуре поведение PowerShell.

В качестве альтернативы вы можете использовать оператор -ceq для сопоставления с регистром (но все еще с учетом культурных особенностей).
($args[0].Equals('red', 'CurrentCulture') даст вам поведение, эквивалентное .IndexOf() решение выше).

Как правило, этот подход позволяет использовать более сложные методы сопоставления , такие как использование оператора -match на основе регулярных выражений или оператора -like на основе групповых символов .


Приведенные выше решения находят индекс первого соответствующего элемента, если таковой имеется.

К найти индекс последнего соответствующий элемент , если есть, используйте:

Примечание. Хотя существует метод [Array]::FindAll() для возврата всех элементов , соответствующих данному предикату ( критерий), существует нет прямой метод для нахождения всех индексов .


[1] Обратите внимание, что вы делаете не нужно * 11 16 *, оператор подвыражения массива для создания массива из индивидуально перечисляемых элементов: нумерация их с помощью ,, достаточно только оператора конструктора массива *1121*:
$array = 'blue','red','purple','pink'

1 голос
/ 17 февраля 2020

Похоже, домашнее задание для меня. В любом случае, как уже упоминалось, все будет намного проще, если вы правильно отформатируете свой код. Также проще, если вы называете свои переменные, а не полагаетесь на $_, потому что он меняется по мере прохождения через вложенный l oop.

Есть и другие способы сделать это - хотите ли вы индекс номер или содержание? Я предположил последний

$array = @('blue','red','purple','pink') 
$array2 = @('brown','red','black','yellow')
ForEach ($a in $array) { 
    if ($array2 -contains $a) { 
        Write-Host "`$array2 contains the `$array1 string $a" 
    } 
}

$array2 contains the $array1 string red
0 голосов
/ 17 февраля 2020
  1. Это практический пример, который использует BinarySearch и полагается на ваш поисковый массив, отсортированный по свойству «интереса».
  2. Использование IComparer для принудительной настройки нечувствительности к регистру

    # BinarySearch needs a sorted array
    $mySortedArray = Get-ChildItem $env:TEMP | Sort-Object -Property Name
    # Provide files available on your machine
    $anotherArray = @(
      'mat-debug-23484.log'
      'MSIaa547.LOG'.ToLower()
    )
    foreach ($item in $anotherArray) {
      $index = $null
      # BinarySearch defaults to being case sensitive
      $index = [array]::BinarySearch($mySortedArray.Name, $item,[Collections.CaseInsensitiveComparer]::Default)
      # If no matches found index will be negative
      if ($index -ge 0) {
        Write-Host ('Index {0} filename {1} found!' -f $index, $mySortedArray[$index].Name) -ForegroundColor Green
      }
    }
    
    # Adjusted to meet your example code
    $array = @('blue','red','purple','pink') 
    $array2 = @('brown','red','black','yellow') | Sort-Object
    
    $array | ForEach-Object {
    $currentObject = $_
    $index = $null
    $index = [array]::BinarySearch($array2, $currentObject, [System.Collections.CaseInsensitiveComparer]::Default)
    if ($index -ge 0) {
        Write-Host ('Index={0} array2 value="{1}" found!' -f $index, $array2[$index]) -ForegroundColor Green
    }
    }
    
0 голосов
/ 17 февраля 2020

Вы также можете сделать for l oop, используя счетчик индекса:

$array  = 'blue','red','purple','pink', 'black'
$array2 = 'brown','red','black','yellow', 'red'

for ($i = 0; $i -lt $array2.Count; $i++) {
    if ($array -contains $array2[$i]) {
        Write-Host "`$array2 contains the the string '$($array2[$i])' at index: $i"
    }
}

Результат:

$array2 contains the the string 'red' at index: 1
$array2 contains the the string 'black' at index: 2
$array2 contains the the string 'red' at index: 4
0 голосов
/ 17 февраля 2020

Вы можете попробовать что-то с счетчиком индекса, который вы можете использовать. Если $array2.ToLower() содержит этот элемент. ToLower (), то l oop через этот второй массив, чтобы узнать, где этот элемент на самом деле находится.

Обратите внимание, что это не сработает для большого количества массивов, поскольку время, которое потребуется для прохождения go, будет увеличиваться и увеличиваться. Но для небольших образцов, подобных этому, он работает нормально.

$array = 'blue','Red','purple','pink', 'browN'
$array2 = 'brown','rEd','black','yellow'

$array | ForEach-Object {
    if ($array2.ToLower() -contains $_.ToLower()) {
        $index = 0
        foreach($arrElement in $array2) {
            #$index++ # based on index starting with 1
            if ($arrElement -eq $_) {
                Write-Host "`$array2 contains the `$array1 string [$_] at index: $index"
            }
            $index++ # based on index starting with 0
        }
    }
}


# produces output
$array2 contains the $array1 string [Red] at index: 1
$array2 contains the $array1 string [browN] at index: 0

Если в $array2 есть дубликатов , вы получите две отдельные строки, которые будут отображать каждый индекс запись.

$array = 'blue','Red','purple','pink', 'browN'
$array2 = 'brown','rEd','black','yellow', 'red'


#Output would be with above code:
$array2 contains the $array1 string [Red] at index: 1
$array2 contains the $array1 string [Red] at index: 4
$array2 contains the $array1 string [browN] at index: 0

...