简体   繁体   English

Powershell-如何通过变量识别,数组上匹配的字符串索引

[英]Powershell- How to identify via variable, the matched string index on a array

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

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

how to get the index of the match string?如何获取匹配字符串的索引?

While PowerShell's -in / -contains operators allow you to test for containment of a given value in a collection (whether a given value is an element of the collection), there is no direct support for getting an element's index using only PowerShell's own features .虽然PowerShell的-in / -contains运算符,可以测试集合中(给定值是否是集合的元素),给定值的遏制,对于获得只使用PowerShell的自己的特色元素的指数没有直接的支持

For .NET arrays (such as the ones created in your question [1] ) you can use their .IndexOf() instance method , which uses case-SENSITIVE comparison based on the current culture;对于.NET数组(例如在您的问题[1] 中创建的数组),您可以使用它们的.IndexOf()实例方法,该方法使用基于当前文化的区分大小写的比较; eg:例如:

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

Note that PowerShell itself is generally case-INSENSITIVE, and with -eq (and in other contexts) uses the invariant culture for comparison.请注意,PowerShell 本身通常不区分大小写,并且使用-eq (以及在其他上下文中)使用不变区域性进行比较。


A case-INSENSITIVE solution based on the invariant culture, using the Array type's static [Array]::FindIndex() method :基于不变区域性的大小写不敏感解决方案,使用 Array 类型的静态[Array]::FindIndex()方法

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

Note that by delegating to a PowerShell script block ( { ... } ) in which each element ( $args[0] ) is tested against the target value with -eq , you implicitly get PowerShell's case-insensitive, culture-invariant behavior.请注意,通过将每个元素 ( $args[0] ) 委托给一个 PowerShell 脚本块 ( { ... } ),其中每个元素 ( $args[0] ) 都通过-eq与目标值进行测试,您隐式地获得了 PowerShell 不区分大小写、文化不变的行为。

Alternatively, you could use the -ceq operator for case- sensitive (but still culture-invariant) matching.或者,您可以使用-ceq运算符进行区分大小写(但仍保持区域性不变)的匹配。
( $args[0].Equals('red', 'CurrentCulture') would give you behavior equivalent to the .IndexOf() solution above). $args[0].Equals('red', 'CurrentCulture')会给你相当于上面的.IndexOf()解决方案的行为)。

Generally, this approach enables more sophisticated matching techniques , such as by using the regex-based -match operator, or the wildcard-based -like operator.通常,这种方法能够使更复杂的匹配技术,例如通过使用基于正则表达式- -match操作者,或基于通配符-like操作。


The above solutions find the index of the first matching element, if any.上面的解决方案找到第一个匹配元素的索引,如果有的话。

To find the index of the last matching element , if any, use:查找最后一个匹配元素的索引(如果有),请使用:

Note: While there is an [Array]::FindAll() method for returning all elements that meet a given predicate (criterion), there is no direct method for finding all indices .注意:虽然有一个[Array]::FindAll()方法可以返回满足给定谓词(标准)的所有元素,但没有直接的方法来查找所有索引


[1] Note that you do not need @() , the array-subexpression operator to create an array from individually enumerated elements: enumerating them with , , the array constructor operator alone is enough: [1]请注意,你不需要@()数组子表达式运算符来创建单独列举元素的数组:与枚举它们,中, 数组构造运营商仅此一项就足以:
$array = 'blue','red','purple','pink'

Looks like a homework exercise to me.对我来说看起来像是家庭作业。 In any case, as mentioned, things are a lot easier if you format your code properly.无论如何,如上所述,如果您正确格式化代码,事情就会容易得多。 It's also easier if you name your variables rather than relying on $_ , because it changes as it goes through a nested loop.如果您命名变量而不是依赖$_ ,这也更容易,因为它会随着嵌套循环而变化。

There are also other ways to do this - do you want the index number or the contents?还有其他方法可以做到这一点 - 你想要索引号还是内容? I assumed the latter我以为是后者

$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

You can try something with an index counter you can use.您可以尝试使用可以使用的索引计数器。 If $array2.ToLower() contains that element.ToLower(), then loop through that second array to find out where that element actually is.如果$array2.ToLower()包含该 element.ToLower(),则循环遍历第二个数组以找出该元素的实际位置。

Note that this is not going to work for large amount of arrays as the time it will take to go through would get larger and larger.请注意,这不适用于大量数组,因为它花费的时间会越来越大。 But, for small samples like this one, it works fine.但是,对于像这样的小样本,它工作正常。

$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

If there are duplicates in the $array2 , you'll get two separate lines that would show each index entry.如果$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

You could also do a for loop using an index counter:您还可以使用索引计数器执行for循环:

$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"
    }
}

Result:结果:

 $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
  1. This is a practical example that uses BinarySearch and relies on your look-up array being sorted by the property of "interest".这是一个实际示例,它使用 BinarySearch 并依赖于按“兴趣”属性排序的查找数组。
  2. Uses IComparer to force case insensitivity使用 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 } }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM