PHP divise la chaîne délimitée en paires clé / valeur (tableau associatif))

j'ai une chaîne comme celle-ci:

key1value1key2value2key3value3key4value4key5value5

et j'aimerais que ce soit un tableau associatif pour que je puisse faire:

echo $myArray['key1']; // prints value1
echo $myArray['key3']; // prints value3
//etc...

je sais que je peux exploser sur le revers, mais je ne sais pas comment partir de là.

9
demandé sur Rizier123 2011-03-13 18:32:19

3 réponses

utilisant un simple regex via preg_match_all et array_combine est souvent l'option la plus courte et la plus rapide:

 preg_match_all("/([^\\]+)\\([^\\]+)/", $string, $p);
 $array = array_combine($p[1], $p[2]);

ceci est bien sûr un cas particulier. Les deux clés et valeurs sont séparés par un \ antislash, comme le sont toutes les paires d'entre eux. L'expression régulière est également un peu plus long en raison de la nécessaire double évasion.

cependant ce schéma peut être généralisé à d'autres chaînes de style key:value, .

Distinct key:value, séparateurs

les variations courantes incluent : et = comme séparateurs clé/valeur, et , ou et et d'autres comme délimiteurs de paires. Le regex devient assez évident dans de tels cas (avec le /x indicateur de lisibilité):

 #                    ↓    ↓    ↓
 preg_match_all("/ ([^:]+) : ([^,]+) /x", $string, $p);
 $array = array_combine($p[1], $p[2]);

, ce Qui rend très facile l'échange : et , pour d'autres délimiteurs.

  • signe " Égal = au lieu de : deux-points.
  • par exemple \t comme délimiteur de paires (tab-clé séparée:listes de valeurs)
  • Classique & ou ; comme séparateur entre des paires valeur / clé.
  • ou juste \s espaces ou \n newlines Pair.

autoriser des délimiteurs variables

vous pouvez le rendre plus flexible / indulgente en permettant différents délimiteurs entre clés/valeurs/ paires:

 #                    ↓      ↓       ↓
 preg_match_all("/ ([^:=]+) [:=]+ ([^,+&]+) /x", $string, $p);

où les deux key=value,key2:value2++key3==value3 fonctionneraient. Ce qui peut avoir du sens pour plus d'human-friendlinies (alias non-technical users).

limite alphanumérique clés

souvent, vous pouvez vouloir interdire tout sauf les identificateurs classiques key . Il suffit d'utiliser un motif de chaîne de mots \w+ pour faire passer le regex sur les occurences indésirables:

 #                   ↓   ↓    ↓
 preg_match_all("/ (\w+) = ([^,]+) /x", $string, $p);

c'est l'approche la plus triviale. Si OTOH vous voulez affirmer / contraindre toute la clé / chaîne de valeur à l'avance, puis d'élaborer une preg_match("/^(\w+=[^,]+(,|$))+/", …

la Bande des espaces ou des citant

vous pouvez sauter quelques étapes post-traitement (comme trim sur les clés et les valeurs) avec un petit ajout:

 preg_match_all("/ \s*([^=]+) \s*=\s* ([^,]+) (?<!\s) /x", $string, $p);

ou par exemple des citations facultatives:

 preg_match_all("/ \s*([^=]+) \s*=\s* '? ([^,]+) (?<![\s']) /x", $string, $p);

extraction de style INI

et vous pouvez élaborer une méthode D'extraction de fichier INI de base:

 preg_match_all("/^ \s*(\w+) \s*=\s* ['\"]?(.+?)['\"]? \s* $/xm", $string, $p);

veuillez noter que ce n'est qu'un brut sous-ensemble des régimes INI communs.

Alternative: parse_str()

si vous avez déjà une chaîne de caractères key=value&key2=value2 , alors parse_str fonctionne comme un charme. Mais en le combinant avec strtr peut même traiter d'autres délimiteurs variables:

 #                         ↓↓    ↑↑
 parse_str(strtr($string, ":,", "=&"), $pairs);

qui a un couple de pour et contre de le sien:

  • encore plus courte que l'approche regex à deux lignes.
  • Prédéfine un mécanisme d'échappement bien connu, tel que %2F pour les caractères spéciaux).
  • ne permet pas de faire varier les délimiteurs, ou les délimiteurs non délimités à l'intérieur.
  • convertit automatiquement keys[]= en tableaux, que vous pouvez ou non vouloir cependant.

Alternative: explode + foreach

vous trouverez de nombreux exemples de clé manuelle/extension de chaîne de valeur . Bien que ce soit souvent plus de code. explode est quelque peu surutilisé dans PHP en raison d'hypothèses d'optimisation. Après le profilage s'avère souvent être plus lent cependant en raison de la manuel foreach et la collection de tableaux.

17
répondu mario 2017-05-23 12:09:41

Que penser de quelque chose comme ceci :

$str = 'key1\value1\key2\value2\key3\value3\key4\value4\key5\value5';
$list = explode('\', $str);

$result = array();
for ($i=0 ; $i<count($list) ; $i+=2) {
    $result[ $list[$i] ] = $list[$i+1];
}

var_dump($result);

Qui serait que vous obtenez :

array
  'key1' => string 'value1' (length=6)
  'key2' => string 'value2' (length=6)
  'key3' => string 'value3' (length=6)
  'key4' => string 'value4' (length=6)
  'key5' => string 'value5' (length=6)



Fondamentalement, ici, l'idée est de:

  • fractionner la chaîne
  • qui vous donnera un tableau tel que 'key1', 'value1', 'key2', 'value2', ...
  • et, ensuite, itérez sur cette liste, avec un saut de 2, en utilisant chaque fois :
    • un élément la clé -- celle pointée par $i
    • celui juste après lui comme la valeur -- celui pointé par $i+1
6
répondu Pascal MARTIN 2011-03-13 15:36:42

Je ne suis pas si bon avec RegExp mais que dire de ce code de ligne

parse_str(preg_replace("/key(.*?)\value(.*?)(\|$)/", "key=value&", $input_lines), $output);
0
répondu Wasim A. 2016-12-03 19:57:07