PHP: Есть ли простой способ разбить список чисел (в виде строки, например "1-3,5,7-9") в массив? - PullRequest
5 голосов
/ 19 октября 2011

Я пытался найти это и здесь, и в Google, поэтому, если я пропустил что-то очевидное, я прошу прощения. Возможно, я просто не знаю названия для форматирования этих чисел.

То, что я хочу сделать, это начать со строки, например "1-3,5,7-9", и превратить ее в массив PHP со следующими записями: 1,2,3,5, 7,8,9

Я знаю, как это сделать, используя preg_split на запятой, затем перебирая и расширяя любые метки, но я чувствую, что должен быть более простой / лучший способ.

EDIT

Я не прояснил это, но строка должна включать SPANS! Это означает, что если моя строка была "1-9", мой результирующий массив должен быть "1,2,3,4,5,6,7,8,9" НЕ ПРОСТО "1,9". Извините за то, что до сих пор не ясно.

Ответы [ 5 ]

11 голосов
/ 19 октября 2011

Не совсем уверен, что вы подразумеваете под «расширением».В любом случае, вот как я бы это сделал с explode и range:

$input = '1-3,5,7-9';
$output = array();

foreach (explode(',', $input) as $nums) {
    if (strpos($nums, '-') !== false) {
        list($from, $to) = explode('-', $nums);
        $output = array_merge($output, range($from, $to));
    } else {
        $output[] = $nums;
    }
}

Если есть лучший способ, который не использует eval (или модификатор PCRE e), я ничего не знаю.

Вот, для вашего развлечения , однострочник (который, к сожалению, использует eval), который возвращаеттот же результат, но ...

Отказ от ответственности : использование eval не рекомендуется в большинстве случаев, поскольку это может создать угрозы безопасности и другие проблемы. Я бы не использовал это , но это все еще возможно.

С учетом сказанного, вот оно:

$output = explode(',', preg_replace('/([0-9]*)-([0-9]*)/e', 'implode(",", range($1, $2));', $input));
2 голосов
/ 15 июля 2014

Упомянутая выше процедура работает хорошо, но имеет ряд недостатков:

  1. Пробелы в строке нарушают процедуру
  2. Дубликаты не удаляются, например, 5,4-7 дают 5,4,5,6,7
  3. Числа не отсортированы.

Я изменил код для решения этих проблем:

function parsenumbers($input)
{
    /*
     * This routine parses a string containing sets of numbers such as:
     * 3
     * 1,3,5
     * 2-4
     * 1-5,7,15-17
     * spaces are ignored
     * 
     * routine returns a sorted array containing all the numbers
     * duplicates are removed - e.g. '5,4-7' returns 4,5,6,7
     */
    $input = str_replace(' ', '', $input); // strip out spaces
    $output = array();
    foreach (explode(',', $input) as $nums)
    {
        if (strpos($nums, '-') !== false)
        {
            list($from, $to) = explode('-', $nums);
            $output = array_merge($output, range($from, $to));
        }
        else
        {
            $output[] = $nums;
        }
    }

    $output = array_unique($output, SORT_NUMERIC); // remove duplicates
    sort($output);

    return $output;
}
1 голос
/ 19 октября 2011
$str = '1-3,5,7-9';
$arr = explode(',', $str);
$result = array();
foreach($arr as $a){
  $x = explode('-', $a);
  if(count($x) === 2){
    $x = range($x[0], $x[1]);
  }
  $result = array_merge($result, $x);
}
print_r($result);

Не уверен, насколько это эффективно, но он выполняет свою работу.

1 голос
/ 19 октября 2011

Я не знаю простой встроенный способ, поскольку это не что-то общее, я сомневаюсь, что есть что-то встроенное.

То, как вы описываете, звучит как разумный подход. Это можно сделать всего за одну итерацию строки, но если это не известная проблема с производительностью, я бы не стал беспокоиться об этом.

0 голосов
/ 19 октября 2011

Ушел, чтобы сделать это, и я вернулся, чтобы увидеть уже 2 ответа. (

<?php
function arrex($s){
    $arr = explode("-", $s);
    $v=$arr[0] + 1;
    $val = array();
            while($v!=$arr[1]){
                 $val[$v] = $v;
                   $v++;
            }
    array_unshift($val, $arr[0]);
    array_push($val, $arr[1]);
return $val;
}
$s = "1-9";
print_r(arrex($s));
?>

Выходы

Array
(
    [0] => 1
    [1] => 2
    [2] => 3
    [3] => 4
    [4] => 5
    [5] => 6
    [6] => 7
    [7] => 8
    [8] => 9
)
...