Convert results to an array - arrays

I've got this code:
$myarray = #(#(0..3) | foreach {(#(0..$_) | Measure-Object -Sum).Sum})
[array]::indexof($myarray,2)
$myarray contains the values 0,1,3,6 so I was hoping [array]::indexof($myarray,3) would return the value 2, but it does not. it returns -1.
I'm assuming that the thing I think is an array isn't actually an array, so I'm assuming the thing I'm assigning to $myarray needs to get converted to an array somehow, clearly I'm doing it wrong.

An easier way of getting values in an array by index number is like this:
$myarray[2]
Sorry, misunderstood your problem. To get the first occurrence of a value in the array, try this:
$myarray.IndexOf([double]3)

Figured it out, sorry. Its an array of doubles, not a array of ints. This works (and is actually what I wanted, i.e. the element contiaing 2016):
$array = #(0..64) | foreach {[int](#(0..$_) | Measure-Object -Sum).Sum}
[array]::indexof($array,2016)

Related

[array]::Reverse() method not working on Get-Content return object

I am writing a script to install/uninstall a collection of software. Some of this software must be installed before others, and when uninstalling they need to go in reverse order. I am attempting to design this script to read a text file containing the paths to all of the .msi files. This way I can read them with Get-Content in appropriate order, then if they need to be uninstalled I can read the same file and just reverse the array.
I'm new to powershell, but it's my understanding that get-object returns an object of type [array]. Microsoft's documentation on Get-Content doesn't specify a return type but every discussion of Get-Content on stack overflow describes the output as an array.
Here's the problem:
When I store the output of Get-Content to a variable $data = Get-Content -Path "C:\my\data.txt" then I print what's stored in $data write-host $data I get the expected output:
line 1
line 2
line 3
etc...
However
When I try to reverse $data = [array]::Reverse($data). It returns null
When I manually create an array $letters = #("a","b","c") and reverse it $letters = [array]::reverse($letters) then the out put of write-host $letters is, as expected:
c
b
a
Here's the question
Why is my call to [array]::reverse($data) returning null? instead of doing as I would expect in my latter example [array]::reverse($letters)?
NOTE: the only difference between those two examples is how I created the array. So either the return type of get-content is not an array, or their is something uniquely different about the returned array that I am missing.
The [array]::reverse() method does not output the array in reverse, it simply reverses it in place, so given:
$x = 'A','B','C'
[array]::reverse($x)
$x
That will output:
C
B
A
If you want to have a second variable that is a reverse of an existing array you can clone the array to the second variable, and then reverse the array contained in the second variable:
$x = 'A','B','C'
$y = $x.clone()
[array]::reverse($y)
At this point $x = 'A', 'B', 'C' while $y = 'C', 'B', 'A'.
I thought I would share that I was able to accomplish my goal using a different line of code.
$data = ($data[($data.Length-1)..0])
This reversed my Get-Content return object. But it doesn't answer my question why the reverse method returns null.

powershell sort & subsort multidimensional array

I'm new at PowerShell. I'm working on how to do a sort & sub-sort of a multidimensional array. I have an array of addresses:
$Addresses += ,#($FirstName, $LastName, $Street, $City, $State, $ZIP);
I need to use the array in two ways. First sorted by last name then first name. Then later I need it sorted by state then city then last name.
I've figured out a one-level sort by last name:
$Addresses = $Addresses | sort-object #{Expression={$_[1]}; Ascending=$TRUE}
But I can't figure out how to sub-sort the resulting array by first name.
Any suggestions?
Thanks
UPDATE: Ok, I found the solution. I was so close. To sort by last name then first, use the expression:
$Addresses = $Addresses | sort-object #{Expression={$_[1],$_[0]}; Ascending=$TRUE}
Simple once I wrapped my brain about Sort-Object.

How do I create an empty array of arrays in Powershell?

I want to create an empty array of arrays in Powershell to hold "tuples" of values (arrays are immutable).
Therefore I try something like:
The type of $arr is Object[]. I've read that += #(1,2) appends the given element (i.e. #(1,2)) to $arr (actually creates a new array). However, in this case it seems that the arrays are concatenated, why?
$arr = #()
$arr += #(1,2)
$arr.Length // 2 (not 1)
If I do as follows, it seems that $arr contains the two arrays #(1,2),#(3,4), which is what I want:
$arr = #()
$arr += #(1,2),#(3,4)
$arr.Length // 2
How do I initialize an empty array of arrays, such that I can add one subarray at a time, like $arr += #(1,2)?
The answer from Bruce Payette will work. The syntax seems a bit awkward to me, but it does work. At least it is not Perl.
Another way to do this would be with an ArrayList. To me, this syntax is more clear and more likely to be understood by another developer (or myself) in six months.
[System.Collections.ArrayList]$al = #()
$al.Add(#(1,2))
$al.Add(#(3,4))
foreach ($e in $al) {
$e
$e.GetType()
}
The + operator concatenates arrays. To add an array as a single element, prefix the element to add with a comma. Something like #() + , (1,2) + , (3, 4).
As far as I can tell, you can't do it natively in PowerShell, nor can you do it with the [System.Array] type. In both cases, you seem to need to define both the length and the type of the array. Because I wanted a completely empty array of arrays, with the ability to store any type of value in the array, I did it this way.
$x=[System.Collections.ArrayList]::new()
$x.Count
$x.GetType()
$x.Add([System.Collections.ArrayList]::new()) > $null
$x.Count
$x[0].Count
$x[0].GetType()
$x[0].Add("first element") > $null
$x.Count
$x[0].Count
$x[0][0]

create a new variable for each loop in a foreach-loop

How can I put $org into an array together with $count?
Like this example array:
$myArray = #{
1="SampleOrg";
2="AnotherSampleOrg"
}
Another example:
$myArray = #{
$count="$org";
$count="$org"
}
Example foreach:
$count=0;get-organization | foreach {$count++; $org = $_.Name.ToString();write-host $count -nonewline;write-host " $org"}
$answer = read-host "Select 1-$count"
The above will display:
1 SampleOrg
2 AnotherSampleOrg
Select 1-2:
What I would like to do afterwards is to put the array to use in a switch.
Example:
switch ($answer)
{
1 {$org=myArray[1]} #<-- or whatever that corresponds to "SampleOrg"
2 {$org=myArray[2]} #<-- or whatever that corresponds to "AnotherSampleOrg"
}
You have to initialize your hashtable somewhere before the loop:
$myArray = #{}
and add a
$myArray.Add($count, $org)
to your foreach-loop.
EDIT: For the discussion about hastable/array see the whole thread ;) I just kept the name of the variable from the original posting
Looks like you're confusing arrays and Hashtables. Arrays are ordered, and indexed by an numeric value. Hashtables are associative, and indexed by any value that has equality defined.
This is array syntax
$arr = #(1,2,3)
and this is Hashtable syntax
$ht = #{red=1;blue=2;}
For your question, the following will work
$orgs = #(get-organization | % { $_.Name })
this will create a 0 based array, mapping int -> OrgName, so
$orgs[$answer]
will get the correct name. Or if you're using 1 based indexing
$orgs[$answer-1]
Note, I removed the switch, as there's no reason for it.

why select -index array doesn't work, powershell

i need to add numbers that don't belong to a linear sequence to retrieve specified indexed folders, i make this attempts :
$a =ls | ?{$_.psiscontainer} | sort creationtime
Then i try to select only some of the folders(fail):
$a | select -Index (100, 101, (103..109))
Whit this simplified array i don't have problems:
$a | select -Index (103..109)
how can i add those numbers?
I try this, forcing the conversion to an array, but the process of conversion fails and i don't know why, if i get the type of the inner members of the array they are already Int32, so i don't understand the error.
$a | select -Index #(100, 101, (103..109))
Parameter -Index is of type int[]. That means that what you pass in as an argument, it has to be an array of numbers.
Imho the simplest way is just to add the arrays like this:
0..100 | select -Index (2,3,5 + 20..30 + 50,60)
Note that you don't have to do ((2,3,5) + (20..30) + (50,60)), because the comma operator has higher priority than plus and interval operator.
For this example, you can get the same result using array slicing:
$a[100,101 + 103..109]

Resources