0

General task: I need to replace numbers in an array and build /replace a string based on a matrix.

In detail: I have an array with two columns, user and ID (=Describtion). From the second column, I need to take the ID, divide it into two pieces, replace the numbers by characters, rebuild a string out of those two parts and put it back into the first array.

Like something:

$Users = Get-some-content()

$Users
User          ID (Describtion)
-------------- -----------
User1          12345678   
User2          87654321


$UsersFirstPart = @($Users.Description)
$UsersFirstPart = @($UsersFirstPart.substring(0,4))

$UsersSecondPart = @($Users.Description)
$UsersSecondPart = @($UsersSecondPart.substring(4,4))


$UsersFirstPart = $UsersFirstPart | ForEach-Object {     $_.replace("0","A").replace("1","B").replace("3","C")}
     
$UsersSecondPart = $UsersSecondPart| ForEach-Object {     $_.replace("0","Z").replace("1","X").replace("3","Y")}


### Then I need to build the string together like ### 
$UserNew = $UserFristPart + “.” + $UserSecondPart

Then I need to exchange the NewUserIDs with the original ones. At the end, it should look like:

User          ID
-------------- -----------
User1          AB.CD   
User2          DE.FG

Any help is much appreciated!

4
  • Your desired output does not match with what you are doing for the $UsersSecondPart. Please show us the full range of replacement characters for the first- and second part of the ID value. Commented Dec 9, 2020 at 13:24
  • The value of ID is always 8 digits from 0 to 9. This is then devided in the 2 parts a 4 digits. Both parts can then still contain digits from 0 to 9. And for both parts there is a matrix a replacement (1=A, 2=B, etc...). Commented Dec 9, 2020 at 14:15
  • In that case, your example does not show this. Please edit the question and supply a correct example and better explanation of what you want. Commented Dec 9, 2020 at 14:19
  • Sorry if that's to unclear. Die Value ID is given and in my example the same as description (ID = description) Commented Dec 16, 2020 at 7:25

1 Answer 1

1

I agree with @Theo's comments the question could be more clear. I don't understand where $User.Desription comes from, since it's not in the columns. Based on your description I'm going to ignore that.

I came up with the following demo:

# Build some sample data:
$Objects =
@(
    [PSCustomObject]@{
        User = 'MrJones'
        ID   = 1234
    }
    [PSCustomObject]@{
        User = 'MrsHowel'
        ID   = 5678
    }
    [PSCustomObject]@{
        User = 'MrSmith'
        ID   = 9012
    }
)

$Objects |
ForEach-Object{
    $FirstPart = ([char[]]$_.ID.ToString().SubString(0,2)) 
    $FirstPart = $FirstPart.ForEach( { [Char](65 + [String]$_) } )
    
    $SecondPart = ([char[]]$_.ID.ToString().SubString(2))     
    $SecondPart = $SecondPart.ForEach( { [Char](65 + [String]$_) } )

    $_.ID = ($FirstPart -join '') + '.' + ($SecondPart -join '')
}

$Objects

Output:

User     ID
----     --
MrJones  BC.DE
MrsHowel FG.HI
MrSmith  JA.BC

There's a little complexity in some of the casting and working with PowerShells underlying type conversion system. However, this basically maps the digits in the ID to an ASCII charter code using simple arithmetic. For example "A" is [Char]65 then [Char](0+65) is "A". So assuming the replacement map progresses as described this should do it.

I could've looped the other way looking for each character code, but at a glance I felt like that would be less efficient. So I started with this approach.

Update:

Considering the question hasn't been updated with a map of numbers to characters, I asked myself what if it were. After all there are only 10 digits so this should be pretty easy to demonstrate. So assuming the previous answer wasn't accurate meaning you can't rely on the ASCII character code here's another approach that would be easy to adjust regardless.

$ResolveNumberToLetter =
@{
    0 = 'A'; 1 = 'B'; 2 = 'C'; 3 = 'D'
    4 = 'E'; 5 = 'F'; 6 = 'G'; 7 = 'H'
    8 = 'I'; 9 = 'J'
}

$Objects =
@(
    [PSCustomObject]@{
        User = 'MrJones'
        ID   = 1234
    }
    [PSCustomObject]@{
        User = 'MrsHowel'
        ID   = 5678
    }
    [PSCustomObject]@{
        User = 'MrSmith'
        ID   = 9012
    }
)

$Objects |
ForEach-Object{
    $FirstPart = ([char[]]$_.ID.ToString().SubString(0,2))
    $FirstPart = $FirstPart.ForEach( { $ResolveNumberToLetter[ [Int][String]$_ ] } )
    

    $SecondPart = ([char[]]$_.ID.ToString().SubString(2))     
    $SecondPart = $SecondPart.ForEach( { $ResolveNumberToLetter[ [Int][String]$_ ] } )

    $_.ID = ($FirstPart -join '') + '.' + ($SecondPart -join '')
}

This example uses a hash table to store and later resolve the relationship between digits and letters. Then in the loop instead of figuring out the relative ASCII character code just look up the value from the hash table.

This example does have the same casting difficulties so I wanted to explain that a bit. Something like [Char]"0" will return 48 which is the character code for "0", and you can't look up 48 in our new table, nor can you perform the appropriate math as we had in the previous example. However, if you cast a string "0" to an [int] you will indeed get 0. In short converting to a string before converting to int resolves the issue.

Note: I may work on a 3rd example to side step the [int][char] example. Will update further if successful.

Sign up to request clarification or add additional context in comments.

4 Comments

Hi, sorry if I was unclear. The ID is the same as description.
OK but I don't think that's important for demonstrating the concept. Above should be sufficient for that. One thing missing from the question was what numbers are should be mapped to what characters. So the ASCII example was based on an assumption. I updated the answer with an example that can define the character map.
Hi Steven, thanks a lot. The second example does exactly the magic I was looking for! Awesome!
Glad to hear it. If you're happy with the answer please accept. Thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.