2016-06-22 9 views
0

Der folgende Code richtig passt:die Spiele einer Regex in ein mehrdimensionales Array

  • letter 'c' followed by digit
  • letter 'c' followed by digit dash digit
  • digit may be followed by an other digit enclosed in square parentheses []

und erstellt ein Array wie dies zu erwarten:

Array 
(
    [0] => Array 
    (
     [start] => 4 
     [end]=> 8 
    )   
    [1] => Array 
    (
     [start] => 2 
     [end]=> 
    ) 
    [2] => Array 
    (
     [start] => 3 
     [end] => 5 
    ) 
    [3] => Array 
    (
     [start] => 6[2] 
     [end] => 
    ) 
    [4] => Array 
    (
     [start] => 8[4] 
     [end] => 10 
    ) 
    [5] => Array 
    (
     [start] => 14 
     [end] => 21[5] 
    ) 
) 

Code:

$str = "a2c4-8|a6c2,c3-5,c6[2],c8[4]-10,c14-21[5]"; 

$re = "~c(?<start>\d+(?:\[\d+])?)(?:-(?<end>(?&start)?))?~"; 

$myarray = explode("|",$str); 

foreach ($myarray as $my) { 
    preg_match_all($re, $my, $matches); 

    $res = array_map(function($ms, $me) { 
     return array("start" => $ms, "end" => $me); 
    }, $matches["start"], $matches["end"]); 
} 

echo "<pre>"; 
    print_r($res); 
echo "</pre>"; 

Nun möchte Ich mag zu eine anderen key mit dem Wert der Ziffer hinzufügen nach den a. So zum Beispiel angesichts der oben $str

$str = "a2c4-8|a6c2,c3-5,c6[2],c8[4]-10,c14-21[5]". 

die a Werte sind: 2 und 6 und das Ergebnis Array erwartet würde die folgende sein. Beachten Sie, dass6 für jede c wiederholt wird.

Array 
(
    [0] => Array 
    (
     [a] => 2 
     [start] => 4 
     [end]=> 8 
    )   
    [1] => Array 
    (
     [a] => 6 
     [start] => 2 
     [end]=> 
    ) 
    [2] => Array 
    (
     [a] => 6 
     [start] => 3 
     [end] => 5 
    ) 
    [3] => Array 
    (
     [a] => 6 
     [start] => 6[2] 
     [end] => 
    ) 
    [4] => Array 
    (
     [a] => 6 
     [start] => 8[4] 
     [end] => 10 
    ) 
    [5] => Array 
    (
     [a] => 6 
     [start] => 14 
     [end] => 21[5] 
    ) 
) 
+0

Da jeder Array-Schlüssel eindeutig sein muss, ist es nicht möglich. –

+0

Ok. Ich habs. Ich habe ein bisschen meine Frage geändert. Bitte schauen Sie sich den editierten Post und das erwartete Ergebnis an. – Nicero

+0

Was passiert, wenn "a" nie definiert wird oder wenn "a" nach dem ersten "c" auftritt? Sind diese Situationen möglich? –

Antwort

1

Sie können das tun:

$str = "a2c4-8|a6c2,c3-5,c6[2],c8[4]-10,c14-21[5]"; 

$re = '~(?:a(?<a>\d+))?c(?<start>\d+(?:\[\d+])?)(?:-(?<end>\g<start>))?~'; 

if (preg_match_all($re, $str, $matches, PREG_SET_ORDER)) { 
    $a = ''; // current value for "a" -----, 
    $result = array_map(function ($i) use (&$a) { 
     if (!empty($i['a'])) $a = $i['a']; 
     else $i['a'] = $a; 

     if (!isset($i['end'])) $i['end'] = ''; 

     foreach ($i as $k=>$v) { 
      if (is_numeric($k)) unset($i[$k]); 
     } 

     return $i; 

    }, $matches); 
} 

print_r($result); 

Aber wenn Sie schon genau wissen, wie der String-Format und wenn Sie es nicht bestätigen müssen, gibt es wahrscheinlich klüger (und schneller) Wege um das gleiche Ergebnis zu erhalten.

Zum Beispiel mit explode und formatierte Strings mit sscanf:

$str = "a2c4-8|a6c2,c3-5,c6[2],c8[4]-10,c14-21[5]"; 

$parts = explode('|', $str); 
$result = []; 

$keys = ['a', 'start', 'end']; 

foreach($parts as $part) { 
    foreach(explode(',', $part) as $k=>$v) { 
     if ($k) 
      list($start, $end) = sscanf($v, 'c%[^-]-%[^,]'); 
     else 
      list($a, $start, $end) = sscanf($v, 'a%dc%[^-]-%[^,]'); 

     $result[] = array_combine($keys, [$a, $start, $end]); 
    } 
} 

print_r($result); 
+0

Perfekt. Ich schätze die Alternative mit 'sscanf', an die ich nie gedacht hätte .. – Nicero

Verwandte Themen