DigitalSewage
DigitalSewage

Reputation: 11

Updating Multi-Dimensional Array not working - (looked at other similar questions - no help)

I am trying to create an array of usernames with a list of eventIDs that I can update and add new users i.e ( ('user1', '23,4523'), ('user2', '5670,2300'), ('user3','321,1299') )

When I initialize the array with the first user and update that user with additional events, I get the expected results.

PS> $usrProfile
user1
4567,1234

When I add a new user ('user2', '6688') instead of getting an array count of '2', it is still '1' and the array returns array object details..... Ok, so I think that works

Length         : 2
LongLength     : 2
Rank           : 1
SyncRoot       : {user1, 4567,1234,2300}
IsReadOnly     : False
IsFixedSize    : True
IsSynchronized : False
Count          : 2

Length         : 2
LongLength     : 2
Rank           : 1
SyncRoot       : {user2, 6688}
IsReadOnly     : False
IsFixedSize    : True
IsSynchronized : False
Count          : 2

.... then the wheels come off when I update 'user2', the original 'user1' record disappears and 'user2' has the updated value, but loses the initial value. Also, initially $item[0] in the foreach loop returns the username, after adding a new user $item[0] returns object info..

Length         : 2
LongLength     : 2
Rank           : 1
SyncRoot       : {System.Object[], System.Object[]}
IsReadOnly     : False
IsFixedSize    : True
IsSynchronized : False
Count          : 2

Length         : 2
LongLength     : 2
Rank           : 1
SyncRoot       : {user2, 7009}
IsReadOnly     : False
IsFixedSize    : True
IsSynchronized : False
Count          : 2

These are commands...

$usrProfile = @( )
$usrProfile = ,(funcUpdateUserProfile "user1" 4567  $usrProfile)
$usrProfile.count
$usrProfile = ,(funcUpdateUserProfile "user1" 1234  $usrProfile)
$usrProfile.count
$usrProfile = ,(funcUpdateUserProfile "user1" 2300  $usrProfile)
$usrProfile.count
$usrProfile = ,(funcUpdateUserProfile "user2" 6688  $usrProfile)
$usrProfile.count
$usrProfile = ,(funcUpdateUserProfile "user2" 7009  $usrProfile)
$usrProfile.count
$usrProfile

I have spent several days on this and am making no progress.... thanks and gratitude in advance for anyone who can spot what I'm doing wrong.....here is the code......

function funcUpdateUserProfile ($userName,  $tmpINTEventID, $tmpUserProfileArray)  {
  $Global:updUserProfileArray = @()
  $initFlag         = $false
  $UpdUserFlag      = $false
  $tmpEventStr = $tmpINTEventID.tostring()
  if ($tmpUserProfileArray.length -eq 0 ) {
     $updUserProfileArray  += ,( ("$userName" , "$tmpEventStr")  )
     $initFlag         = $true
  }else {
       ForEach ($item in $tmpUserProfileArray) {
         if  ( ($item[0].toString()) -like "*$userName*" ) {
            $UpdUserFlag      = $true
            $user      = $item[0].toString()
            $tmpOldStr = $item[1].toString()
            $updStr    = $tmpOldStr +','+ $tmpEventStr
            $updUserProfileArray   += ,(   ($user, ("$updStr")) ) 
          }elseif ( !(($item[0].toString()) -like "*$userName*")   )  {
            $user      = $item[0].toString()
            $tmpOldStr = $item[1].toString()
            $updUserProfileArray   += ,(   ($user, ("$tmpOldStr"))    )  
          }#End if Else
        }#End ForEach
  }#end IfElse
  if ( ($initFlag -eq $false ) -AND ($UpdUserFlag -eq $false)  ) {
     $updUserProfileArray += ,(  ($userName, "$tmpEventStr")  ) 
   }
  return $updUserProfileArray
}

Upvotes: 1

Views: 247

Answers (2)

postanote
postanote

Reputation: 16126

If I am following you, is this what you were after with your use case.

# If I am following you, is this what you were after with your use case.

# Initial multidementonal array
[System.Collections.ArrayList]$ScoreDetails = @()
$ScoreDetails = @( 
    @('Player001', '200'), 
    @('Player002', '199') 
)

# Arrray count
$ScoreDetails.Count
# Results
<#
2
#>

# Array details
$ScoreDetails | 
Select-Object -Property '*'
# Results
<#
Count          : 2
Length         : 2
LongLength     : 2
Rank           : 1
SyncRoot       : {Player001, 200}
IsReadOnly     : False
IsFixedSize    : True
IsSynchronized : False

Count          : 2
Length         : 2
LongLength     : 2
Rank           : 1
SyncRoot       : {Player002, 199}
IsReadOnly     : False
IsFixedSize    : True
IsSynchronized : False
#>


# Ask for new entry
'Enter NEXT player score details'
$name  = Read-Host 'Name'
$score = Read-host 'Score'
# Results
<#
Enter NEXT player score details
Name: Player003
Score: 300
#>

<#
Comma, to tell PowerShell to add a new row the multidimensional array
#>
$ScoreDetails += ,(@($name,$score))

# Arrray count
$ScoreDetails.Count
# Results
<#
3
#>

# Update the array
for(
        $OuterLoop = 0
        $OuterLoop -lt 3
        $OuterLoop ++
)
{
    for(
            $InnerLoop = 0
            $InnerLoop -lt 2
            $InnerLoop ++
    )
    {
        "The value of [$OuterLoop][$InnerLoop] ---> " + 
        $ScoreDetails[$OuterLoop][$InnerLoop]
    }
}
# Results
<#
The value of [0][0] ---> Player001
The value of [0][1] ---> 200
The value of [1][0] ---> Player002
The value of [1][1] ---> 199
The value of [2][0] ---> Player003
The value of [2][1] ---> 300

#>
# Arrray count
$ScoreDetails.Count
# Results
<#
3
#>

# Array details
$ScoreDetails | 
Select-Object -Property '*'
# Results
<#
Count          : 2
Length         : 2
LongLength     : 2
Rank           : 1
SyncRoot       : {Player001, 200}
IsReadOnly     : False
IsFixedSize    : True
IsSynchronized : False

Count          : 2
Length         : 2
LongLength     : 2
Rank           : 1
SyncRoot       : {Player002, 199}
IsReadOnly     : False
IsFixedSize    : True
IsSynchronized : False

Count          : 2
Length         : 2
LongLength     : 2
Rank           : 1
SyncRoot       : {Player003, 300}
IsReadOnly     : False
IsFixedSize    : True
IsSynchronized : False
#>


# Modify an entry
$ScoreDetails[0][1] = 250

# Arrray count
$ScoreDetails.Count
# Results
<#
3
#>

# Array details
$ScoreDetails | 
Select-Object -Property '*'
# Results
<#
Count          : 2
Length         : 2
LongLength     : 2
Rank           : 1
SyncRoot       : {Player001, 250}
IsReadOnly     : False
IsFixedSize    : True
IsSynchronized : False

Count          : 2
Length         : 2
LongLength     : 2
Rank           : 1
SyncRoot       : {Player002, 199}
IsReadOnly     : False
IsFixedSize    : True
IsSynchronized : False

Count          : 2
Length         : 2
LongLength     : 2
Rank           : 1
SyncRoot       : {Player003, 300}
IsReadOnly     : False
IsFixedSize    : True
IsSynchronized : False
#>

Update as per your comment

using the cast [System.Collections.ArrayList] would not allow me to do what I wanted - still, it drew my attention to considering the "cast" of my array.

... as per my follow-up comment to you. For example:

$ScoreDetails = @()

$ScoreDetails = @( 
    @('Player001', '200'), 
    @('Player002', '199') 
)

# ...

'Enter NEXT player score details'
$name  = Read-Host 'Name'
$score = Read-host 'Score'

$ScoreDetails += ,(@($name,$score))

# ...

for(
        $OuterLoop = 0
        $OuterLoop -lt 3
        $OuterLoop ++
)
{
    for(
            $InnerLoop = 0
            $InnerLoop -lt 2
            $InnerLoop ++
    )
    {
        "The value of [$OuterLoop][$InnerLoop] ---> " + 
        $ScoreDetails[$OuterLoop][$InnerLoop]
    }
}

#...

$ScoreDetails | 
Select-Object -Property '*'
# Results
<#
Count          : 2
Length         : 2
LongLength     : 2
Rank           : 1
SyncRoot       : {Player001, 200}
IsReadOnly     : False
IsFixedSize    : True
IsSynchronized : False

Count          : 2
Length         : 2
LongLength     : 2
Rank           : 1
SyncRoot       : {Player002, 199}
IsReadOnly     : False
IsFixedSize    : True
IsSynchronized : False

Count          : 2
Length         : 2
LongLength     : 2
Rank           : 1
SyncRoot       : {Player003, 100}
IsReadOnly     : False
IsFixedSize    : True
IsSynchronized : False
#>

$ScoreDetails[0][1] = 250
$ScoreDetails | 
Select-Object -Property '*'
# Results
<#
Count          : 2
Length         : 2
LongLength     : 2
Rank           : 1
SyncRoot       : {Player001, 250}
IsReadOnly     : False
IsFixedSize    : True
IsSynchronized : False

Count          : 2
Length         : 2
LongLength     : 2
Rank           : 1
SyncRoot       : {Player002, 199}
IsReadOnly     : False
IsFixedSize    : True
IsSynchronized : False

Count          : 2
Length         : 2
LongLength     : 2
Rank           : 1
SyncRoot       : {Player003, 100}
IsReadOnly     : False
IsFixedSize    : True
IsSynchronized : False
#>

$ScoreDetails[1][1] = '199, 300'
$ScoreDetails | 
Select-Object -Property '*'
# Results
<#
Count          : 2
Length         : 2
LongLength     : 2
Rank           : 1
SyncRoot       : {Player001, 250}
IsReadOnly     : False
IsFixedSize    : True
IsSynchronized : False

Count          : 2
Length         : 2
LongLength     : 2
Rank           : 1
SyncRoot       : {Player002, 199, 300}
IsReadOnly     : False
IsFixedSize    : True
IsSynchronized : False

Count          : 2
Length         : 2
LongLength     : 2
Rank           : 1
SyncRoot       : {Player003, 100}
IsReadOnly     : False
IsFixedSize    : True
IsSynchronized : False
#>

Upvotes: 0

Mathias R. Jessen
Mathias R. Jessen

Reputation: 175084

Nested/jagged arrays are usually not the best choice of data structure in PowerShell (as you seem to have found out :) ), and I'd suggest using a hashtable (@{}) instead:

$userEventIDs = @{
  'user1' = @(23, 4523)
  'user2' = @(5670, 2300) 
  'user3' = @(321, 1299)
}

Adding a new event ID for a specific user now becomes trivial (notice I'm using +=, not =):

PS ~> $userEventIDs['user1'] += @(4567, 1234)
PS ~> $userEventIDs['user1'].Count
4

Upvotes: 4

Related Questions