2011-10-08 5 views
7

Estoy un poco desconcertado por esta, y estoy luchando para encontrar ejemplos similares en línea en este momento.Convirtiendo un rango o arreglo parcial, en la forma "3-6" o "3-6,12", en una matriz de números enteros, como 3,4,5,6,12

Al trabajar en PHP, quiero tomar entrada, probablemente de un campo de formulario, de una "lista de valores", un "rango" o una combinación de ambos, en el formulario;

3,5,6,9,11,23 

o

3-20 

o

3-6,8,12,14-50 

quiero devolver estos como una matriz de enteros, por lo que, por ejemplo

3,4,5,6,8,12,14,15,16... 

no voy a escribir todos ellos, ¡pero la idea es bastante obvia!

¿Hay alguna función disponible que hace esto, o dónde comenzaría a escribir una?

+0

explotar en ',' y expandir en guiones. – NullUserException

+1

El procedimiento inverso se puede encontrar aquí: [Acortando la lista de números con guiones entre números consecutivos] (http://stackoverflow.com/q/9448129/367456). – hakre

Respuesta

10

Usted probablemente está buscando el range función y implode:

$input = '3,5,6,9,11,23,14-77'; 

$result = preg_replace_callback('/(\d+)-(\d+)/', function($m) { 
    return implode(',', range($m[1], $m[2])); 
}, $input); 

le da:

3,5,6,9,11,23,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77 

Demo

Cómo funciona: Usted tiene básicamente dos fichas en la cadena: la gama token (1-n) (definido como regular expression: (\d+)-(\d+)) y el repliegue (todo lo demás).

preg_replace_callback permite la expansión de la cadena de tokens mediante una función de devolución de llamada.Esa función de devolución de llamada simplemente expande los dos valores numéricos coincidentes en la lista separada por comas usando la función range de PHP y implode.

Después de que la cadena está en un formato normalizado que pueda simplemente explode que:

// as array: 

print_r(explode(',', $result)); 

Full Demo

+0

Buena solución, +1. PD: ¿No había una función PHP incorporada que aceptaba cosas como '1..9' y' range (1, 9) '? –

0

No tengo ninguna función. Puede explotar la cadena con "," y luego verificar si es una expresión de rango e insertar los valores.

Ejemplo de código (no sé cómo la matriz debe ser similar & no admite valores negativos, pero podría ser fácilmente añadidos):

$input = "3-6,8,12"; 
$output = array(); 


$strings = explode(",", $input); 
foreach($strings as $value) { 
    if(stripos($value, "-") === false) { 
     $output[(int) $value] = (int) $value; 
    } else { 
     $range = explode("-", $value); 

     $range[0] = (int) $range[0]; 
     $range[1] = (int) $range[1]; 

     if($range[0] <= $range[0]) { 
      for ($i = $range[0]; $i <= $range[1]; $i++) { 
       $output[$i] = $i; 
      } 
     } 
    } 
} 

var_dump($output); 

Esto produce una salida:

array(6) { [3]=> int(3) [4]=> int(4) [5]=> int(5) [6]=> int(6) [8]=> int(8) [12]=> int(12) } 
+0

O bien, podría usar 'range()' para presionar y guardar algunas líneas de código;) –

1
function list2array ($list) { 
    $array = explode(',', $list); 
    $return = array(); 
    foreach ($array as $value) { 
     $explode2 = explode('-', $value); 
     if (count($explode2) > 1) { 
      $range = range($explode2[0], $explode2[1]); 
      $return = array_merge($return, $range); 
     } else { 
      $return[] = (int) $value; 
     } 
    } 
    return $return; 
} 

Resultado:

php > print_r(list2array('3-6,8,12,14-50')); 
Array 
(
    [0] => 3 
    [1] => 4 
    [2] => 5 
    [3] => 6 
    [4] => 8 
    [5] => 12 
    [6] => 14 
    [7] => 15 
    [...] 
    [41] => 49 
    [42] => 50 
) 

No tiene informe de errores por cierto, puede ponerlo allí por su cuenta :).

+0

Esto se ve perfecto, voy a probarlo en una hora o dos y le contaré cómo me llevo! ¡Gracias! –

+0

Su bienvenida :) – Sietse

0
<?php 
    $input="1,2,5-9,12,19"; 
    $iarr=explode(",", $input); 



    $oarr=array(); 

    $rex='/([0-9]{1,})\-([0-9]{1,})/'; 

    for($i=0; $i<count($iarr); $i++) { 
     preg_match($rex, $iarr[$i], $arrs); 
     if(!$arrs) { 
      array_push($oarr, $iarr[$i]); 
     } else { 
      $oarr=array_merge($oarr, range($arrs[1], $arrs[2], 1)); 
      /* Save a few lines of code by removing this and using above. Same difference, though 
      for($j=$arrs[1]; $j<=$arrs[2]; $j++) { 
       array_push($oarr, $j); 
      } */ 
     } 
    } 



    print_r($oarr); 
?> 

Resultado:

Array (
    [0] => 1 
    [1] => 2 
    [2] => 5 
    [3] => 6 
    [4] => 7 
    [5] => 8 
    [6] => 9 
    [7] => 12 
    [8] => 19 
) 
0
$str = '2,3,4,5-10'; 
$strArr = explode(',',$str); 
$finalArr = array(); 
$m = array(); 
foreach($strArr as $v) { 
    $m = preg_split(":-:",$v); 
    $start = $m[0]; 
    $finish = (isset($m[1]) ? $m[1] : $m[0]); 
    $range = range($start,$finish); 
    foreach($range as $r) $finalArr[] = $r; 
} 
print_r($finalArr); 
0

una función más:

function arrayFromList($list){ 
    $return = array(); 
    foreach(explode(',',$list) as $item){ 
     if(($dash = strpos($item, '-', 1)) !== FALSE){ 
      $return = array_merge($return, range(substr($item, 0, $dash),substr($item,$dash+1))); 
     } 
     else{ 
      $return[] = (int)$item; 
     } 
    } 
    return $return; 
} 

Ésta es consciente de los números negativos si lo necesita, por lo que la entrada como -4--1,1 también funcionará.

0

Aquí es una formalización/formulación de hakre's excellent answer:

function rangesToList($a, $max) { 
    $a = trim($a); 
    if (isset($max) && substr($a, -1) == "-") { 
     $a .= $max; 
    } 
    $r = preg_replace_callback('/(\d+)-(\d+)/', function($m) { 
     return implode(',', range($m[1], $m[2])); 
    }, $a); 
    return array_map('intval', explode(",", $r)); 
} 

Además de ser encapsulado en una fórmula y un poco más robusto, que también toma un argumento opcional $max para que pueda darle entrada de la siguiente manera:

$in = "2,4,6-8, 12-"; 
$out = rangesToList($in, 14); 

y obtener este

Array 
(
    [0] => 2 
    [1] => 4 
    [2] => 6 
    [3] => 7 
    [4] => 8 
    [5] => 12 
    [6] => 13 
    [7] => 14 
) 
Cuestiones relacionadas