8721 sujets

Développement web côté serveur, CMS

Bonjour à tous,

J'ai une chaîne de caractère simple, comme ceci par exemple : A,B,C,D,(E,F),G,H,(I,J),K

Et je souhaiterais la coupler à chaque virgule. Évidemment je pourrais utiliser explode(), mais là où ça devient compliqué c'est que si cette virgule est contenu dans (), alors il faut ignorer ^^

Et d'autres termes, je souhaiterais un résultat qui me renverrais ce genre de tableau

array('A',
    'B',
    'C',
    'D',
    'E,F',
    'G',
    'H',
    'I,J',
    'K');


Il faudra probablement passer par une expression régulière mais je me perds un peu, si quelqu’un pouvait m'orienter ce serait sympa Smiley smile

Merci Smiley smile
Modifié par Gaylord.P (04 Jul 2015 - 21:23)
Modérateur
Heureusement il existe Regexr pour apprendre,construire et tester ses expressions régulières.
Modifié par Greg_Lumiere (05 Jul 2015 - 10:22)
Bonsoir,

J'ai tenté quelque chose :

$str = "A,B,C,D,(E,F),G,H,(I,J),K";

$pattern = '`\(([A-Z],)+[A-Z]\)`';
$t1 = array();
$t2 = array();
preg_match_all($pattern, $str, $matches);
$group = preg_split($pattern, $str);

foreach($group as $k => $val){
    $t1[] = array_filter(explode(',',$val));
    if(isset($matches[0][$k]))
        $t1[][] = preg_replace("`[\(-\)]`", "", $matches[0][$k]);
}
foreach($t1 as $val){
    foreach($val as $val2){
        $t2[] = $val2;
    }
}

La tableau $t2 renvoie le tableau de ton exemple.
Il y a certainement une meilleure façon de faire mais si ça peut t'aider...
Modifié par Mabedu (05 Jul 2015 - 22:43)
Bonjour,
Sans expression régulière ... C'est un peu plus compliqué que ce que je pensais:


$result = array();
$str = "A,B,C,D,(E,F,Z),G,H,(I,J),K";
$arr_str = explode(",", $str);
$counter = 0;
$open = FALSE;
foreach( $arr_str as $one ){
  if( strpos($one, "(") !== FALSE ){
    $open = TRUE;
    $result[$counter] = str_replace( array("(", ")"), "", $one );
    continue;
  } 
  if( $open ){
    if( strpos($one, ")") !== FALSE ){
      $result[$counter] .= ", " . str_replace( array(")"), "", $one );
      $counter++;
      $open = FALSE;
      continue;
    }

    $result[$counter] .= ", " . str_replace( array(")"), "", $one );
    continue;
  }
  
  $result[$counter] = $one;
  $counter++;
}

print_r($result);

Modifié par loicbcn (06 Jul 2015 - 10:28)
Retour aux regex, pourquoi pas essayer avec preg_match_all et une regex de ce style :
[^(),]+|\([^()]+\)


S'il y a plusieurs niveaux d'imbrication, il y a probablement moyen de s'en sortir avec (?R).
Ou sinon, trouver une combine pour convertir en JSON ou XML puis parser avec les fonctions adéquates.
Fonction qui marche sans regex; en se basant sur la découpe des parenthèses avant celle des virgules.

$str = "A,B,C,D,(E,F,Z),G,H,(I,J),K";
$a1=explode ("(",$str);
echo "<pre>";var_dump($a1);echo "</pre>"; 
foreach($a1 as $s)
{
	$a2[]=explode(")",$s);
}
echo "<pre>";var_dump($a2);echo "</pre>";
foreach($a2 as $a3)
{
	if(count($a3)==1)
	{
		$r[]=explode(",",$a3[0]);	
	}
	else
	{
		$r[][0]=$a3[0];
		$r[]=explode(",",$a3[1]);
	}
}
echo "<pre>";var_dump($r);echo "</pre>";
foreach($r as $tmp)
{
	foreach($tmp as $s)
	{
		if(!empty($s)){$result[]=$s;}	
	}
}
echo "<pre>";var_dump($result);echo "</pre>";
unset($a1,$a2,$a3,$r,$tmp);



Et en cadeau, le résultat des var_dump pour comprendre l'idée

$a1
array(3) {
  [0]=>
  string(8) "A,B,C,D,"
  [1]=>
  string(11) "E,F,Z),G,H,"
  [2]=>
  string(6) "I,J),K"
}


$a2
array(3) {
  [0]=>
  array(1) {
    [0]=>
    string(8) "A,B,C,D,"
  }
  [1]=>
  array(2) {
    [0]=>
    string(5) "E,F,Z"
    [1]=>
    string(5) ",G,H,"
  }
  [2]=>
  array(2) {
    [0]=>
    string(3) "I,J"
    [1]=>
    string(2) ",K"
  }
}


$r
array(5) {
  [0]=>
  array(5) {
    [0]=>
    string(1) "A"
    [1]=>
    string(1) "B"
    [2]=>
    string(1) "C"
    [3]=>
    string(1) "D"
    [4]=>
    string(0) ""
  }
  [1]=>
  array(1) {
    [0]=>
    string(5) "E,F,Z"
  }
  [2]=>
  array(4) {
    [0]=>
    string(0) ""
    [1]=>
    string(1) "G"
    [2]=>
    string(1) "H"
    [3]=>
    string(0) ""
  }
  [3]=>
  array(1) {
    [0]=>
    string(3) "I,J"
  }
  [4]=>
  array(2) {
    [0]=>
    string(0) ""
    [1]=>
    string(1) "K"
  }
}


$result
array(9) {
  [0]=>
  string(1) "A"
  [1]=>
  string(1) "B"
  [2]=>
  string(1) "C"
  [3]=>
  string(1) "D"
  [4]=>
  string(5) "E,F,Z"
  [5]=>
  string(1) "G"
  [6]=>
  string(1) "H"
  [7]=>
  string(3) "I,J"
  [8]=>
  string(1) "K"
}

Modifié par Lothindil (06 Jul 2015 - 11:34)
Si tu veux éviter de partir dans des délires tordus tu peux faire un truc simple comme ça :


<pre>
<?php

function extractMyStuffs($input)
{
  $regex = "#\(([A-Z,]+)\)|([A-Z]+)#";
  $matches = $final = array();

  if (!preg_match_all($regex, $input, $matches)) {
    return null;
  }

  foreach ($matches[1] as $k => $v) {
    $final[] = ("" !== $matches[1][$k]) ? $matches[1][$k]: $matches[2][$k];
  }

  return $final;
}


$in1 = "A,B,C,D,(E,F),G,H,(I,J),K";
$in2 = "(E,F),(I,J)";
$in3 = "A,B,C,D,G,H,,K";

var_dump(extractMyStuffs($in1));
var_dump(extractMyStuffs($in2));
var_dump(extractMyStuffs($in3));

?>
</pre>