In PowerShell I have a array of unique values, e.g. "London Office", "Manchester Office" etc.
What I need to do is create a new array for every value inside the original array, where the name of each array is the value in the original array. I.e. so that the name of each array is:
"London Office", "Manchester Office" etc.
This would seem simple but is stumping me, any help much appreciated.
Use Set-Variable cmdlet. Or, create a global hash table and stuff arrays in its entries with keys from your initial array.
Sounds like you need a hashtable - basically an unordered dictionary:
$Array = "London Office", "Manchester Office"
# Create an empty hashtable
$Hashtable = #{}
foreach($item in $Array){
# create hashtable entry with array $item as key/name, empty array as value
$Hashtable[$item] = #()
}
Now you can access the individual arrays like this:
$Hashtable["Manchester Office"] += "New array item here"
Related
I am trying to sort an hashtable in Powershell with the following structure :
https://i.stack.imgur.com/bjSX6.png
Each value of the hashtable is an array containing multiple elements.
I would like to sort the hashtable based on the value of second element of each array, is it possible ?
Create an ordered dictionary, then enumerate all the key-value pairs in the existing hashtable, sort them by the desired value and then add them to your new ordered dictionary:
# Create ordered dictionary
$ordered = [ordered]#{}
# Sort KVPs by value at index 1 (that's the second element) of the array
$hashtable.GetEnumerator() |Sort-Object { $_.Value[1] } |ForEach-Object {
# Copy the KVP to the ordered dictionary in... order
$ordered[$_.Key] = $_.Value
}
$ordered now contains the same entries as $hashtable, but sorted according to your criteria
I am trying to create a function to loop through json file and based upon specific condition met want to add the value of the json keys to array but not able to accomplish the same.
Following is the json:
$a1 = [ {
"name": "sachin",
"surname": "",
},
{
"name": "Rajesh",
"surname": "Mehta"
}
]
and the function that i have created is below:
function addingkeyval
{
param ($key,
[Array]$tobeaddedarr)
$a1 | Select-Object -Property name,surname | ForEach-Object {
if($_.$key-eq "")
{
}
else
{
$tobeaddedarr +=$_.$key+","
}
}
}
when i cal this function with the statement:
$surnamearr = #()
addingkeyval -key surname -tobeaddedarr $surnamearr
i want the output in the array $surnamearr as below
("Mehta")
somehow i am not able to add the value in the array can anyone help me in achieving the same
$surnamearr = ([string[]] (ConvertFrom-Json $a1).surname) -ne ''
ConvertFrom-Json $a1 converts the JSON array to an array of PowerShell custom objects (type [pscustomobject]).
(...).surname extracts the values of all .surname properties of the objects in the resulting array, using member-access enumeration.
Cast [string[]] ensures that the result is treated as an array (it wouldn't be, if the array in $a1 happened to contain just one element) and explicitly casts to strings, so that filtering nonempty values via -ne '' also works for input objects that happen to have no .surname property.
-ne '' filters out all empty-string elements from the resulting array (with an array as the LHS, comparison operators such as -ne act as array filters rather than returning a Boolean value).
The result is that $surnamearr is an array containing all non-empty .surname property values.
As for what you tried:
$tobeaddedarr +=$_.$key+","
This statement implicitly creates a new array, distinct from the array reference the caller passed via the $tobeaddedarr parameter variable - therefore, the caller never sees the change.
You generally cannot pass an array to be appended to in-place, because arrays are immutable with respect to their number of elements.
While you could pass an mutable array-like structure (such as [System.Collections.Generic.List[object]] instance, which you can append to with its .Add() method), it is much simpler to build a new array inside the function and output it.
Therefore, you could write your function as:
function get-keyval
{
param ($key)
# Implicitly output the elements of the array output by using this command.
([string[]] (ConvertFrom-Json $key).surname) -ne ''
}
$surnamearr = get-keyval surname
Note:
Outputting an array or a collection in PowerShell by default enumerates it: it sends its elements one by one to the output stream (pipeline).
While it is possible to output an array as a whole, via the unary form of ,, the array-construction operator (
, (([string[]] (ConvertFrom-Json $a1).surname) -ne '')), which improves performance, the problem is that the caller may not expect this behavior, especially not in a pipeline.
If you capture the output in a variable, such as $surnamearr here, PowerShell automatically collects the individual output objects in an [object[]] array for you; note, however, that a single output object is returned as-is, i.e. not wrapped in an array.
You can wrap #(...) around the function call to ensure that you always get an array
Alternatively, type-constrain the receiving variable: [array] $surnamearr = ..., which also creates an [object[]] array, or something like [string[]] $surnamearr = ..., which creates a strongly typed string array.
$hash = #{}
$hash.x1 = 1
$hash.x2 = 2
Can I display the hash table's values like this?
$hash.[x1,x2]
$hash.[x1,x2] (with dot and bare words) will not work, but you can use the index operator directly on a hashtable with an array of the key names (as strings). Like this:
$hash['x1','x2']
or like this:
$keys = 'x1', 'x2'
$hash[$keys]
I have an array where each element is a hashtable. Each hashtable has the same keys. Here it is:
#(
#{"MarketShortCode"="abc";"MarketName"="Market1" },
#{"MarketShortCode"="def";"MarketName"="Market2" },
#{"MarketShortCode"="ghi";"MarketName"="Market3" },
#{"MarketShortCode"="jkl";"MarketName"="Market4" }
)
I want a nice elegant way to extract an array containing just the value of the MarketShortCode key. So I want this:
#("abc","def","ghi","jkl")
This is the best I've come up with:
$arr = #()
$hash | %{$arr += $_.MarketShortCode}
$arr
But I don't like that cos its three lines of code. Feels like something I should be able to do in one line of code. Is there a way?
Just do this:
$hash | %{$_.MarketShortCode}
That is, return the value from the block instead of adding it to an array and then dereferencing the array.
If you're using PowerShell 3+, there's even shorter way:
$hash.MarketShortCode
PowerShell automatically applies dot . to each item in an array when it's used this way, but it wasn't supported until v3.
Let's say I have hash like this:
$NATO = #{
"A" = "Alpha";
"B" = "Bravo";
"C" = "Charlie";
# ...
"Y" = "Yankee";
"Z" = "Zulu";
}
I could get all values of hash using $NATO.keys key collection:
$NATO[$NATO.keys] # gives me all values
But if I want to pass subset of keys, to get subset of values, I can't do that:
$NATO["BUNYK".ToCharArray()] # gives me nothing, but I want
# Bravo, Uniform, November, Yankee, Kilo
Do you know how this could be done?
You could also pipe the string array into a ForEach-Object loop:
[string[]]'BUNYK'.ToCharArray() | % { $NATO[$_] }
The hash table stores the keys as objects, not necessarily simple strings. The keys in your example are strings, but you're trying to access them as [char] objects. The easiest way to handle your example is to cast the [char[]] array to a [string[]] array:
$NATO[([string[]] "BUNYK".ToCharArray())]