1

I was asking myself how easily you could convert an Array of Numbers Like = 1,2,3,6,7,8,9,12,13,15 into 1 String that "Minimizes" the numbers, so Like = "1-3,6-9,12-13,15".

I am probably overthinking it because right now I don't know how I could achieve this easily.

My Attempt:

$newArray = ""
$array = 1,2,3,6,7,8,9,12,13,15
$before
Foreach($num in $array){
  If(($num-1) -eq $before){
    # Here Im probably overthinking it because I don't know how I should continue
  }else{
    $before = $num
    $newArray += $num
  }
}

3 Answers 3

2

This should working, Code is self explaining, hopefully:

$array  = @( 1,2,3,6,7,8,9,12,13,15 )

$result = "$($array[0])"
$last   = $array[0]

for( $i = 1; $i -lt $array.Length; $i++ ) {

    $current = $array[$i]

    if( $current -eq $last + 1 ) {
        if( !$result.EndsWith('-') ) {
            $result += '-'
        }
    }
    elseif( $result.EndsWith('-') ) {
        $result += "$last,$current"
    }
    else {
        $result += ",$current"
    }
    $last = $current
}

if( $result.EndsWith('-') ) {
    $result += "$last"
}

$result = $result.Trim(',')
$result = '"' + $result.Replace(',', '","') +'"'

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

1 Comment

Other than replacing the ";" with "," and not being in need of the second to last line, its exactly what i searched for, thank you!
1

I have a slightly different approach, but was a little too slow to answer. Here it is:

$newArray = ""
$array = 1,2,3,6,7,8,9,12,13,15
$i = 0
while($i -lt $array.Length)
{
    $first = $array[$i]
    $last = $array[$i]
    # while the next number is the successor increment last
    while ($array[$i]+1 -eq $array[$i+1] -and ($i -lt $array.Length))
    {
        $last = $array[++$i]
    }
    # if only one in the interval, output that
    if ($first -eq $last)
    {
        $newArray += $first 
    }
    else
    {
        # else output first and last
        $newArray += "$first-$last"
    }
    # don't add the final comma
    if ($i -ne $array.Length-1) 
    {
        $newArray += ","
    }
    $i++
}
$newArray

Comments

0

Here is another approach to the problem. Firstly, you can group elements by index into a hashtable, using index - element as the key. Secondly, you need to sort the dictionary by key then collect the range strings split by "-" in an array. Finally, you can simply join this array by "," and output the result.

$array = 1, 2, 3, 6, 7, 8, 9, 12, 13, 15

$ranges = @{ }

for ($i = 0; $i -lt $array.Length; $i++) {
    $key = $i - $array[$i]

    if (-not ($ranges.ContainsKey($key))) {
        $ranges[$key] = @()
    }

    $ranges[$key] += $array[$i]
}

$sequences = @()

$ranges.GetEnumerator() | Sort-Object -Property Key -Descending | ForEach-Object {
    $sequence = $_.Value
    $start = $sequence[0]

    if ($sequence.Length -gt 1) {
        $end = $sequence[-1]
        $sequences += "$start-$end"
    }
    else {
        $sequences += $start
    }
}

Write-Output ($sequences -join ",")

Output:

1-3,6-9,12-13,15

Comments

Your Answer

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