【问题标题】:Powershell - print the list length respectivelyPowershell - 分别打印列表长度
【发布时间】:2021-11-12 13:56:32
【问题描述】:

我想在 Powershell 中写两件事。 例如; 我们有一个清单:

$a=@('ab','bc','cd','dc')

我想写:

1 >> ab
2 >> bc
3 >> cd
4 >> dc

我希望这是基于列表长度的动态。

感谢您的帮助。

【问题讨论】:

  • 1..$a.Length |% {"$_ >> $($a[$_-1])"}。我没有给出这个答案,因为如果你是初学者,几乎不可能理解,而且有更明显、更明确的方法可以做到这一点,但拆开看看它是如何工作的可能会很有趣。

标签: arrays list powershell indexing


【解决方案1】:

使用for 循环,以便跟踪索引:

for( $i = 0; $i -lt $a.Count; $i++ ){
  "$($i + 1) >> $($a[$i])"
}

解释这是如何工作的:

  • for 循环由三个部分定义,由分号 ; 分隔。

    • 第一部分声明变量,在本例中我们定义$i = 0。这将是我们的索引参考。
    • 第二部分是循环继续的条件。只要$i 小于 $a.Count,循环就会继续。我们不想超出列表的长度,否则您会遇到不良行为。
    • 第三部分是循环的每次迭代结束时发生的事情。在这种情况下,我们希望每次将计数器 $i 增加 1($i++ 是“increment $i by 1”的简写)
    • 这个符号的细微差别比我所包含的要多,但它与循环的工作方式无关。您可以在Unary Operators 上阅读更多信息。
  • 对于循环体本身,我会解释字符串

    • 返回对象而不分配给变量(例如此字符串)实际上与使用Write-Output 相同。
      • 在大多数情况下,Write-Output 实际上是可选的(通常不是您想要在屏幕上显示文本的内容)。 My answer here 更详细地介绍了不同的 Write- cmdlet、输出流和重定向。
    • $()sub-expression operator,用于返回表达式以在父表达式中使用。在这种情况下,我们返回$i + 1 的结果,它被插入到最终的字符串中。
      • 它的独特之处在于它可以直接在字符串中使用,这与相似但不同的array sub-expression operatorgrouping operator 不同。
      • 如果没有子表达式运算符,您会得到类似0 + 1 的内容,因为它会插入$i 的值,但会按字面意思呈现 + 1
    • >> 之后,我们使用另一个子表达式将$a$ith 索引的值插入到字符串中。
      • 虽然简单的variable expansion 会将数组$a.ToString() 值插入到最终字符串中,但必须在子表达式或@987654351 中引用数组的索引 @ 将按字面意思呈现。

Your solution 使用foreach 并在循环中执行$a.IndexOf($number) 确实 工作,但$a.IndexOf($number) 用于获取当前索引,.IndexOf(object) 通过迭代数组来工作直到找到匹配的对象引用,然后返回索引。对于大型数组,每次迭代将花费越来越长的时间。 for 循环没有这个限制。

考虑以下具有更大数组的示例:

# Array of numbers 1 through 65535
$a = 1..65535

# Use the for loop to output "Iteration INDEXVALUE"
# Runs in 106 ms on my system
Measure-Command { for( $i = 0; $i -lt $a.Count; $i++ ) { "Iteration $($a[$i])" } }

# Use a foreach loop to do the same but obtain the index with .IndexOf(object)
# Runs in 6720 ms on my system
Measure-Command { foreach( $i in $a ){ "Iteration $($a.IndexOf($i))" } }

要注意的另一件事是,虽然您可以更改 属性 并在集合元素上执行方法,但您不能更改非集合集合的元素值(任何不在集合中的集合) System.Concurrent.Collections 命名空间),当它的枚举器正在使用时。虽然不可见,foreach(以及相关的ForEach-Object)隐式调用集合的.GetEnumerator() 循环方法。这不会像其他 .NET 语言那样引发错误,但 IMO 应该如此。它似乎会接受集合的新值,但一旦退出循环,该值将保持不变。

这并不是说永远不应该使用 foreach 循环,或者说你做了任何“错误”的事情,但我觉得在你发现自己陷入困境之前应该知道这些细微差别适合更好构造的情况。

【讨论】:

    【解决方案2】:

    好吧,

    我已经解决了;

    $a=@('ab','bc','cd','dc')
    $a.Length
    
    foreach ($number in $a) {
        $numberofIIS = $a.IndexOf($number)
        Write-Host ($numberofIIS,">>>",$number)
    
        }
    

    【讨论】:

    • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
    【解决方案3】:

    Bender 的回答很棒,但我个人尽可能避免使用 for 循环。它们通常需要一些笨拙的数组索引和丑陋的设置......整个事情最终看起来像象形文字。

    使用foreach 循环,我们的工作是跟踪索引(这是这个答案与您的不同的地方),但我认为最终它比 for 循环更具可读性。

    $a = @('ab', 'bc', 'cd', 'dc')
    
    # Pipe the items of our array to ForEach-Object
    # We use the -Begin block to initialize our index variable ($x)
    $a | ForEach-Object -Begin { $x = 1 } -Process {
        # Output the expression
        "$x" + ' >> ' + $_
    
        # Increment $x for next loop
        $x++
    }
    
    # -----------------------------------------------------------
    
    # You can also do this with a foreach statement
    # We just have to intialize our index variable 
    # beforehand
    
    $x = 1
    foreach ($number in $a){
        # Output the expression
        "$x >> $number"
    
        # Increment $x for next loop
        $x++
    }
    

    【讨论】:

    • 每种循环类型都有其用途。 Foreach 和 foreach-object 也可以工作,但我觉得在循环之外定义一个计数器很尴尬。但这在很大程度上是一种偏好。如果您确实想在循环中修改集合,那么 for 循环也是唯一的方法(AFAIK 除了使用并发集合)。
    • 奇怪的是,修改 foreach 循环元素不会导致与 C# 不同的异常,尽管新值本质上不会在循环之外持续存在
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-03
    • 1970-01-01
    相关资源
    最近更新 更多