powershell execute math on array elements - powershell

I'm looking to perform math on two arrays but i'm always ending up executing on the arrays itself and not it elements. how do i call each element from both arrays and perform math on them one by one?
$array1 = (1,2,3)
$array2 = (1,2,3)
$do | % {$array1 + $array2}
this adds the arrays together as in:
1
2
3
1
2
3
but the result i am looking for is the following:
2
4
6
how do i have to go about this?

One way would be to use for like this:
$array1 = (1,2,3)
$array2 = (1,2,3)
for ($i = 0; $i -lt $array1.Length; $i++){
$array1[$i] + $array2[$i]
}
Output:
2
4
6

Related

How to Iterate through an index of n using different index of p

I am doing this in PowerShell, although the question isn't tied to a language.
lets say that I have an indexed array of size n called accounts, and another indexed array of size p called rows. I want to go through each of the items in row and use an account to do something. In my real world example, I have excel rows and I need to log into accounts in the accounts array in a round-robin fashion. the size of these arrays can be anything from 1 to n, and they will very likely not be the same size as the other. What math problem can I use to ensure that, regardless of the size of the array, I get the iterations below (assume $rows.Count is 500 and $accounts.Count is 12:
rows[1] - accounts[1]
rows[2] - accounts[2]
rows[3] - accounts[3]
rows[4] - accounts[4]
rows[5] - accounts[5]
rows[6] - accounts[6]
rows[7] - accounts[7]
rows[8] - accounts[7]
rows[9] - accounts[8]
rows[10] - accounts[9]
rows[11] - accounts[10]
rows[12] - accounts[11]
rows[13] - accounts[12]
rows[14] - accounts[1]
rows[15] - accounts[2]
rows[16] - accounts[3]
rows[17] - accounts[4]
My attempts have landed on this so far:
for ($i = 0; $i -lt $rows.Count; $i++) {
$k = 0
$j = $accounts.Count
if ($i -le $j) {
$k = $j
}
else {
$k = $i % $j
}
$rows[$i] - $accounts[$k]
}
I think that modulus is the key, but I can't seem to finish the equation.
Indeed, using %, the modulus operator, is key; a PowerShell-idiomatic solution (it simply prints the paired array elements):
$rows = 1..500
$accounts = 1..12
$i = 0
$rows.ForEach({ '{0} - {1}' -f $_, $accounts[$i++ % $accounts.Count] })
Note that array indices in PowerShell / .NET are 0-based.

Processing items within a powershell array - multiple items

I have been reading about arrays in powershell and hash tables, I know the basic workings of an array and how to use foreach loop to get items within the array, my challange here is slightly different. I would like to pay what I call a multi dimension array to a script, and process the items contained within the array.
What is my setup.
$x = (1,"Server1",3,1),(4,"Server2",6,2),(3,"Server3",4,3)
$k = 'serverid','servername','locationid','appid' # key names correspond to data positions in each array in $x
$h = #{}
For($i=0;$i -lt $x[0].length; $i++){
$x |
ForEach-Object{
[array]$h.($k[$i]) += [string]$_[$i]
}
}
What am i trying to achieve ?
I am trying to achieve the structure of a database table within powershell. So literally treating each array item as a row.
So for example
(1,"Server1",3,1),(4,"Server2",6,2),(3,"Server3",4,3)
could be thought of as a table like below
enter image description here
I then want to loop for each item in the array to get the values, similar to the below example
[0].serverid = 1, [0].servername = server1, [0].locationid = 3, [0].applicationID = 1
[1].serverid = 4, [1].servername = server2, [1].locationid = 6, [1].applicationID = 2
what have I done ?
$x = (1,"Server1",3,1),(4,"Server2",6,2),(3,"Server3",4,3)
$k = 'serverid','servername','locationid','appid' # key names correspond to data positions in each array in $x
$h = #{}
For($i=0;$i -lt $x[0].length; $i++){
$x |
ForEach-Object{
[array]$h.($k[$i]) += [string]$_[$i]
}
}
$x
for ($i = 0; $i -lt $x.Count; $i++)
{
$myserverid = $x[$i][0]
$myservername = $x[$i][1]
$mylocationid = $x[$i][2]
$myappid = $x[$i][3]
write-host $myserverid
}
The Issues
If I set the following $x = (1,"Server1",3,1), then the loop is somewhat incorrect which is why I think the approach is wrong (more than one item works i.e $x = (1,"Server1",3,1),(4,"Server2",6,2),(3,"Server3",4,3)). The loop only works if you have more than one item within the array, hence why I want to re-examine the way the loop works.
Thanks in advance
Your approach relies on a nested (jagged) array: That is, you have an array of subarrays, each of which represents the tuple of values you want to assign to properties.
If there's only one subarray, you must create the nested array explicitly, using the unary form of , the array constructor operator:
# Construct a 1-element array that contains the 4-element subarray.
$x = , (1,"Server1",3,1)
With two or more, subarrays, you implicitly get a nested array:
# Construct a 3-element array, each element of which contains a 4-element subarray.
$x = (1,"Server1",3,1), (4,"Server2",6,2), (3,"Server3",4,3)
Note that in PSv5+ you could use a custom class to solve your problem:
class Custom {
[int] $serverid; [string] $servername;[int] $locationid; [int] $appid
Custom($propValueArray) {
$this.serverid = $propValueArray[0]; $this.servername = $propValueArray[1]; $this.locationid = $propValueArray[2]; $this.appid = $propValueArray[3]
}
}
# Use an array cast to construct [Custom] instances.
# Note the need for (...) around the array, because casts have high
# precedence in PowerShell.
[Custom[]] ((1,"Server1",3,1), (4,"Server2",6,2), (3,"Server3",4,3))
This would allow for processing such as:
# Construct all objects
$objects = [Custom[]] ((1,"Server1",3,1), (4,"Server2",6,2), (3,"Server3",4,3))
# Process each object.
foreach ($object in $objects) {
($myserverid = $object.serverid) # assign a property to a var; `()` also outputs
# ...
}

perl better method for counting each array element occurance

I have 2 arrays, one is the root array, which contains huge mount of elements. Another is the tested array, all of which elements is a subset of root array. I want to construct a new array, with size equal to root arrays, and its element value at a specific position represents the count of that element in the tested array.
Below codes works well when 2 array size is small. But the practical problem I meet is that, the root arrays has about 15000 elements, and there are about 14000 tested arrays.
I wonder to have better algorithm. Do you guys have some suggestions?
my #root=qw(1 2 3 4 5 6 7 8 10);
my #aa=qw(1 1 2 3);
my #count;
foreach my $eleroot(#root){
my $mathnum=0;
my ($i) = grep { $root[$_] ~~ $eleroot } 0 .. $#root;
foreach my $eleaa(#aa){
if ($eleroot==$eleaa){
$mathnum++;
}
}
$count[$i]=$mathnum;
}
print #count;
A better algorithm would be to use a hash to keep counts. For your sample arrays, it would look like this. (And will run considerably faster than your solution).
#!/usr/bin/perl
use strict;
use warnings;
my #root=qw(1 2 3 4 5 6 7 8 10);
my #aa=qw(1 1 2 3);
print join("\t", #root), "\n";
my %seen;
for my $data (#aa) {
$seen{$data}++;
}
print join("\t", map {$_ // '0'} #seen{#root}), "\n";
Output is:
1 2 3 4 5 6 7 8 10
2 1 1 0 0 0 0 0 0
#seen{#root} is a hash slice keyed by the #root array. If no item was found for any of the #root elements, the map supplies a zero.
The map {$_ // '0'} portion is saying pass to join a count if $_ has a count otherwise pass a zero.

What does 'foreach(1..4)' mean in Perl?

In Perl, what does foreach(1..4) mean? Specifically the two periods. I've been having trouble finding an answer.
In Perl, 1..4 produces 1 2 3 4 so you're looping through all the numbers from 1 to 4, assigning each value in turn to $_.
.. is one of the Range Operators
It is known as the range operator.
It creates a range between the two operands...
foreach(1..4)
It means your loop runs from 1 to 4
or
creates a range between the two operands
Example equals to
my $min = 999;
foreach $item (1, 2, 3, 4)
{
$min = $item if $min > $item;
}
print "Min = $min\n"; # expects Min = 1

Powershell - Looping through objects in batches of 3

I have an object which contains 7 items.
$obj.gettype().name
Object[]
$obj.length
7
I want to loop through in batches of 3. I do NOT want to use the modulus function, I actually want to be able to create a new object with just the 3 items from that batch. Pseudo code:
$j=0
$k=1
for($i=0;$i<$obj.length;$i+=3){
$j=$i+2
$myTmpObj = $obj[$i-$j] # create tmpObj which contains items 1-3, then items 4-6, then 7 etc
echo "Batch $k
foreach($item in $myTmpObj){
echo $item
}
$k++
}
Batch 1
item 1
item 2
item 3
Batch 2
item 4
item 5
item 6
Batch 3
Item 7
Regards,
ted
Your pseudo code is almost real. I have just changed its syntax and used the range operator (..):
# demo input (btw, also uses ..)
$obj = 1..7
$k = 1
for($i = 0; $i -lt $obj.Length; $i += 3) {
# end index
$j = $i + 2
if ($j -ge $obj.Length) {
$j = $obj.Length - 1
}
# create tmpObj which contains items 1-3, then items 4-6, then 7 etc
$myTmpObj = $obj[$i..$j]
# show batches
"Batch $k"
foreach($item in $myTmpObj) {
$item
}
$k++
}
The output looks exactly as required.
See if this one may work as required (I assume your item n is an element of $obj)
$obj | % {$i=0;$j=0;$batches=#{}}
if($i!=3 and $batches["Batch $j"]) { $batches["Batch $j"]+=$_; $i+=1 }
else {$i=1;$j+=1;$batches["Batch $j"]=#($_)}
} {$batches}
Should return an HashTable ($batches) with keys such as "Batch 1", "Batch 2", ... each key related to an array of three items.