Skip to main content

Parse a string, and convert it into a series of sequential numbers. It works similar to Acrobat's print specified pages input box.

<?php

/**
 * Parse a string, and convert it into a series of sequential numbers.
 * It works similar to Acrobat's print specified pages input box.
 *
 * Examples:
 *
 *     input: "1, 2, 3, 4, 5, 6" --> output: 1, 2, 3, 4, 5, 6
 *     input: "1-6"        --> output: 1, 2, 3, 4, 5, 6
 *     input: "1-6"        --> output: 1, 2, 3, 4, 5, 6
 *     input: "1 - -6"        --> output: 1, 2, 3, 4, 5, 6
 *     input: "0 - 0"        --> output: 0
 *     input: "1, 4-6, 2"      --> output: 1, 2, 4, 5, 6
 *     input: "6,3-1"        --> output: 1, 2, 3, 6
 *
 *  // Sample Usage:
 * $range = range_string("6, 3-1");
 *
 * @author Jay Williams <myd3.com>
 * @license MIT License
 * @link http://gist.github.com/125557
 */

define('RANGE_ARRAY_SORT', 1);
define('RANGE_ARRAY', 2);
define('RANGE_STRING_SORT', 3);
define('RANGE_STRING', 4);

function range_string($range_str, $output_type = RANGE_ARRAY_SORT)
{
  // Remove spaces and nother non-essential characters
  $find[]    = "/[^\d,\-]/";
  $replace[] = "";

  // Remove duplicate hyphens
  $find[]    = "/\-+/";
  $replace[] = "-";

  // Remove duplicate commas
  $find[]    = "/\,+/";
  $replace[] = ",";

  $range_str = preg_replace($find, $replace, $range_str);

  // Remove any commas or hypens from the end of the string
  $range_str = trim($range_str,",-");

  $range_out = array();
  $ranges    = explode(",", $range_str);

  foreach($ranges as $range)
  {

    if(is_numeric($range) || strlen($range) == 1)
    {
      // Just a number; add it to the list.
      $range_out[] = (int) $range;
    }
    else if(is_string($range))
    {

      // Is probably a range of values.
       $range_exp = preg_split("/(\D)/",$range,-1,PREG_SPLIT_DELIM_CAPTURE);

      $start = $range_exp[0];
      $end   = $range_exp[2];

      if($start > $end)
      {
        for($i = $start; $i >= $end; $i -= 1)
        {
          $range_out[] = (int) $i;
        }
      }
      else
      {
        for($i = $start; $i <= $end; $i += 1)
        {
          $range_out[] = (int) $i;
        }
      }

    }
  }

  switch ($output_type) {
    case RANGE_ARRAY_SORT:
      $range_out = array_unique($range_out);
      sort($range_out);

    case RANGE_ARRAY:
      return $range_out;
      break;

    case RANGE_STRING_SORT:
      $range_out = array_unique($range_out);
      sort($range_out);

    case RANGE_STRING:

    default:
      return implode(", ", $range_out);
      break;
  }
}

?>