MrSchism
MrSchism

Reputation: 43

Joining character array elements

An alphanumeric string is input, sent to lower, then evaluated. Then, every third letter needs to be capitalized and returned to a string. The number/letter positions are not always the same.

Sample input handling:

$in = read-host "value in"
$var1 = $in.tolower()

So I've given two variables that can be used as an example

$var1 = 1ab23c4def56
# $var1 = a123bcd45e6f  # alternate $var1 for example purposes

$val = ($var1).ToCharArray()

foreach ($n in $val){
    if ($n -notmatch "[0-9]"){
        $alfaNo++
        if ($alfaNo -eq 4){
            $o = $([char]::ToUpper($n))
            $alfaNo = 0
            $n = $o
        }
        echo $n
    }
    else {echo $n}
}
$val

The issue is that the loop shows each appropriate character going to upper, but the change isn't made when $val displayed at the end.

Upvotes: 1

Views: 519

Answers (4)

mjolinor
mjolinor

Reputation: 68243

Another option:

$var1 = '1ab23c4def56'

$i=0
$var1 = 
$([string[]][char[]]$var1 |
foreach { 
 if (++$i %3) { $_ }
  else { $_.ToUpper() }
 }) -join ''

$var1

Upvotes: 1

TheMadTechnician
TheMadTechnician

Reputation: 36287

Looks like you're dealing with Scope issues. While in the ForEach loop the variables are in a scope that don't affect the array that they come from. A simple modification without a complete re-write would be to simply add a new variable, and set it to be the output of your ForEach loop, and then have the ForEach loop output $n instead of echoing it (or in addition to).

Now, so far as I can tell your If statement is just wrong and the correct letters are not in fact being capitalized, but that aside this at least lets your code function as you want:

$var1 = "1ab23c4def56"
# $var1 = a123bcd45e6f  # alternate $var1 for example purposes

$val = ($var1).ToCharArray()
$alfaNo = 0
$NewVal = foreach ($n in $val){
    if ($n -notmatch "[0-9]"){
        $alfaNo++
        if ($alfaNo -eq 4){
            $o = $([char]::ToUpper($n))
            $alfaNo = 0
            $n = $o
        }

    }
    $n
}
$newval -join ''

Personally I'd use a Switch command instead of a ForEach with all those If statements. Something like:

$var1 = "1ab23c4def56"
# $var1 = a123bcd45e6f  # alternate $var1 for example purposes

$inc = 0
$NewVal = Switch($var1 -Split ''){
    {$_ -match "\d"} {$_;continue}
    {$_ -match "[a-z]" -and $inc -lt 2} {$_;$inc++;continue}
    {$_ -match "[a-z]"} {$inc = 0;[char]::toupper($_)}
}
$NewVal -join ''

Upvotes: 2

hysh_00
hysh_00

Reputation: 839

This is another approach. If you want the results in String, you have to create new String object like this.

$var1 = '1ab23c4def56'
$val = ($var1).ToCharArray()

for( $n=0 ; $n -lt $val.length ; $n++)
{
   if( (($n % 3) -eq 2) -AND ($val[$n] -match "[a-z]") )
   {
      $val[$n] = [char]::ToUpper($val[$n])
   }
}

$var1 = New-Object System.String ($val,0,$val.Length)

$var1

Upvotes: 1

Jan Chrbolka
Jan Chrbolka

Reputation: 4454

You're modifying the value of $n but not the original array $val.

Try this...

$var1 = "1ab23c4def56"
# $var1 = a123bcd45e6f  # alternate $var1 for example purposes

$val = ($var1).ToCharArray()

$alfaNo = 0
for($i=0;$i -le $val.Length;$i++){
    if ($val[$i] -notmatch "[0-9]"){
        $alfaNo++
        if ($alfaNo -eq 3){
            $val[$i] = $([char]::ToUpper($val[$i]))
            $alfaNo = 0
        }
        echo $val[$i]
    }
    else {echo $val[$i]}
}
$val

Upvotes: 1

Related Questions