Shortening list of numbers with hyphens between consecutive numbers
Asked Answered
S

3

4

Is there a simple way to take a list of numbers which can be in the range 1 - 15. And put a dash in place of consecutive numbers.

So that for example if you had the following numbers:

1 2 3 5 6 7 10 12

It would output

1 - 3, 5 - 7, 10, 12

Stagy answered 25/2, 2012 at 21:13 Comment(2)
What have you tried? You will find you get the best responses if you post a specific questions (i.e. some code you have tried and how it's not working).Juliusjullundur
Related: How to group numbers in ranges using PHPFresco
R
7
<?php
$n = array (1, 2, 3, 5, 6, 7, 10, 12);
sort ($n);   // If necessary.
$i = 0;
while ($i < count ($n))
  {
    if ($i != 0)
      print (", ");
    $rangestart = $i;
    print ($n [$i++]);
    while ($i < count ($n) && $n [$i] == $n [$i - 1] + 1)
      $i++;
    if ($i > $rangestart + 1)
      print (" - " . $n [$i - 1]);
  }
Reuben answered 25/2, 2012 at 21:31 Comment(0)
T
7
$n = array (1, 2, 4, 5, 7, 8, 10, 11, 12, 13, 14, 16, 17);
$lastindex = count($n)-1;
foreach($n as $k => $i)
{
    if($k == 0) echo $i;
    elseif($i != $n[$k-1]+1) echo ', ' . $i;
    elseif($k == $lastindex || $i+1 != $n[$k+1]) echo ' - ' . $i;
}

The function with explode:

http://codepad.org/DKztLGhe

function shorten( $numbers ){
  $a = explode(' ',$numbers);
  $lastindex = count($a)-1;
  $s = '';
  foreach( $a as $i => $n ){
    if( $i == 0 )                                    $s .=       $n;
    else if( $a[$i-1]+1 != $n )                      $s .=  ', '.$n;
    else if( $i == $lastindex || $n+1 != $a[$i+1] )  $s .= ' - '.$n;
  }
  return $s;
}

print_r(shorten('').'<br>');
print_r(shorten('1').'<br>');
print_r(shorten('1 2').'<br>');
print_r(shorten('1 3').'<br>');
print_r(shorten('1 3 4 6').'<br>');
print_r(shorten('1 3 4 6 7').'<br>');
print_r(shorten('1 2 3 4 5').'<br>');
print_r(shorten('1 2 3 5 6 10 12 13').'<br>');
Thinner answered 25/2, 2012 at 21:38 Comment(3)
Hi, $lastindex is definitely necessary, see codepad.org/4fvWpL6d Please put it back :)Thinner
'Internal server error'. Can't see the link, though I've tested it locally and it worked. On the last item this will return true ($n+1 != $a[$i+1]). There will not be a next item $a[$i+1]Webby
prepend error_reporting(-1) to the script, and you will get notices about nonexistent array indexes.Thinner
F
0

Split your space-delimited values into an array then use a single loop for best time complexity / performance.

Push references into the result array which represent the start of each potential range of numbers. If contiguous values are encountered, just insert/replace the tail end of the reference value.

After populating the result array, implode them with whatever delimiter you wish.

Code: (Demo)

function hyphenate(array $numbers): string {
    $result = [];
    $ref = null;
    foreach ($numbers as $i => $number) {
        if ($ref && $number == $numbers[$i - 1] + 1) {
            $ref = strtok($ref, "-") . "-$number";
        } else {
            unset($ref);
            $ref = $number;
            $result[] =& $ref;
        }
    }
    return implode(',', $result);
}
Fresco answered 4/7 at 4:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.