I want to write two things in Powershell. For example; We have a one list:
$a=@('ab','bc','cd','dc')
I want to write:
1 >> ab
2 >> bc
3 >> cd
4 >> dc
I want this to be dynamic based on the length of the list.
Thanks for helping.
I want to write two things in Powershell. For example; We have a one list:
$a=@('ab','bc','cd','dc')
I want to write:
1 >> ab
2 >> bc
3 >> cd
4 >> dc
I want this to be dynamic based on the length of the list.
Thanks for helping.
Use a for
loop so you can keep track of the index:
for( $i = 0; $i -lt $a.Count; $i++ ){
"$($i + 1) >> $($a[$i])"
}
To explain how this works:
The for
loop is defined with three sections, separated by a semi-colon ;
.
$i = 0
. This will be our index reference.$i
is less than $a.Count
, the loop will continue. We don't want to go past the length of the list or you will get undesired behavior.$i
by 1 each time ($i++
is shorthand for "increment $i
by 1")For the loop body itself, I'll explain the string
Write-Output
.
Write-Output
is actually optional (and often is not what you want for displaying text on the screen). My answer here goes into more detail about the different Write-
cmdlets, output streams, and redirection.$()
is the sub-expression operator, and is used to return expressions for use within a parent expression. In this case we return the result of $i + 1
which gets inserted into the final string.
0 + 1
as it will insert the value of $i
but will render the + 1
literally.>>
we use another sub-expression to insert the value of the $i
th index of $a
into the string.
.ToString()
value of array $a
into the final string, referencing the index of the array must be done within a sub-expression or the []
will get rendered literally.Your solution using a foreach
and doing $a.IndexOf($number)
within the loop does work, but while $a.IndexOf($number)
works to get the current index, .IndexOf(object)
works by iterating over the array until it finds the matching object reference, then returns the index. For large arrays this will take longer and longer with each iteration. The for loop does not have this restriction.
Consider the following example with a much larger array:
# 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))" } }
Another thing to watch out for is that while you can change properties and execute methods on collection elements, you can't change the element values of a non-collection collection (any collection not in the System.Concurrent.Collections
namespace) when its enumerator is in use. While invisible, foreach
(and relatedly ForEach-Object
) implicitly invoke the collection's .GetEnumerator()
method for the loop. This won't throw an error like in other .NET languages, but IMO it should. It will appear to accept a new value for the collection but once you exit the loop the value remains unchanged.
This isn't to say the foreach
loop should never be used or that you did anything "wrong", but I feel these nuances should be made known before you do find yourself in a situation where a better construct would be appropriate.
Okey,
I fixed that;
$a=@('ab','bc','cd','dc')
$a.Length
foreach ($number in $a) {
$numberofIIS = $a.IndexOf($number)
Write-Host ($numberofIIS,">>>",$number)
}
Bender's answer is great, but I personally avoid for
loops if at all possible. They usually require some awkward indexing into arrays and that ugly setup... The whole thing just ends up looking like hieroglyphics.
With a foreach
loop it's our job to keep track of the index (which is where this answer differs from yours) but I think in the end it is more readable then a for loop.
$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++
}