-1

I have a string like this:

$measurements = 'Hauteur/-/175 cm/-/Height/-/5'9''/-/00010/--/Buste (Femme)/-/92 cm/-/Bust (Women)/-/36''/-/00020/--/Taille/-/74 cm/-/Waist/-/29''/-/00022/--/Hanches/-/99 cm/-/Hips/-/39''/-/00023';

I can explode this into an array using the following:

$measurements_array = explode("/-/", $measurements);

However, what I actually need to do is explode into a key->value pair every SECOND occurrence of /-/.

The output should be:

Array(
    [Hauteur] => 185 cm,
    [Height] => 6'1'',
    [Hair / color] => Brown,
    [Eyes] => Brown-Green,
)

So on and so forth.......

I've been messing around for almost an hour trying to get it to output into an array the way I need, but so far its not been going well.

Can anyone help?

Zach Nicodemous
  • 9,097
  • 9
  • 45
  • 68

2 Answers2

1

The data is made up of a series of measurements, separated by a numeric delimiter. Each measurement has a name in French and a metric value, followed by an English version with an Imperial value. Thus, we need to extract four values from each block, and assemle those four values into two rows in an array.

explode() is a little simplistic, given the existence of a numeric delimiter between fields. A regular expression can extract the relevant data in one pass, and all we need do then is assemble it into the final result.

The regular expression here contains four capturing groups to gather the required data, and a non-capturing group for the delimiter.

<?php

$measurements = "Hauteur/-/175 cm/-/Height/-/5'9''/-/00010/--/Buste (Femme)/-/92 cm/-/Bust (Women)/-/36''/-/00020/--/Taille/-/74 cm/-/Waist/-/29''/-/00022/--/Hanches/-/99 cm/-/Hips/-/39''/-/00023";
$regex = "%(.*?)/-/(.*?)/-/(.*?)/-/(.*?)/-/\d{5}(?:/--/){0,1}%";
preg_match_all($regex, $measurements, $matches);

preg_match_all() extracts the data into the $matches array. We get an array like this:

array(5) {
  [0]=>
  array(4) {
    [0]=>    string(45) "Hauteur/-/175 cm/-/Height/-/5'9''/-/00010/--/"
    [1]=>    string(55) "Buste (Femme)/-/92 cm/-/Bust (Women)/-/36''/-/00020/--/"
    [2]=>    string(41) "Taille/-/74 cm/-/Waist/-/29''/-/00022/--/"
    [3]=>    string(37) "Hanches/-/99 cm/-/Hips/-/39''/-/00023"
  }
  [1]=>
  array(4) {
    [0]=>    string(7) "Hauteur"
    [1]=>    string(13) "Buste (Femme)"
    [2]=>    string(6) "Taille"
    [3]=>    string(7) "Hanches"
  }
  [2]=>
  array(4) {
    [0]=>    string(6) "175 cm"
    [1]=>    string(5) "92 cm"
    [2]=>    string(5) "74 cm"
    [3]=>    string(5) "99 cm"
  }
  [3]=>
  array(4) {
    [0]=>    string(6) "Height"
    [1]=>    string(12) "Bust (Women)"
    [2]=>    string(5) "Waist"
    [3]=>    string(4) "Hips"
  }
  [4]=>
  array(4) {
    [0]=>    string(5) "5'9''"
    [1]=>    string(4) "36''"
    [2]=>    string(4) "29''"
    [3]=>    string(4) "39''"
  }
}

We can ignore the first element of $matches as it contains each of the complete matched items. We're interested in the other four elements which contain the results of each matched group.

The first of these match groups contain the French name, the second contains the metric value. The third and fourth contain the English and Imperial versions respectively.

All we need do now is step through the arrays creating the correct keys and values in a new array:

$output = [];
for ($i = 0; $i<count($matches[0]);$i++) {
    $output[$matches[1][$i]]=$matches[2][$i];
    $output[$matches[3][$i]]=$matches[4][$i];
}
var_dump($output);

Output:

array(8) {
  ["Hauteur"]=>
  string(6) "175 cm"
  ["Height"]=>
  string(5) "5'9''"
  ["Buste (Femme)"]=>
  string(5) "92 cm"
  ["Bust (Women)"]=>
  string(4) "36''"
  ["Taille"]=>
  string(5) "74 cm"
  ["Waist"]=>
  string(4) "29''"
  ["Hanches"]=>
  string(5) "99 cm"
  ["Hips"]=>
  string(4) "39''"
}

Demo: https://3v4l.org/i4mQM

  • This is awesome! Exactly what I needed AND you explained it very well so that I can utilize for other needs in the future too. Probably also saved me some headaches tomorrow trying to figure this out myself. Very much appreciated! – Zach Nicodemous Sep 02 '21 at 04:46
0

I had a similar issue once. I used the array_splice() method from this answer.

<?php
$measurements = "Hauteur/-/175 cm/-/Height/-/5'9''/-/00010/--/Buste (Femme)/-/92 cm/-/Bust (Women)/-/36''/-/00020/--/Taille/-/74 cm/-/Waist/-/29''/-/00022/--/Hanches/-/99 cm/-/Hips/-/39";

$measurements_array = explode("/-/", $measurements);

$result = array();

while (count($measurements_array)) {
    list($key,$value) = array_splice($measurements_array, 0, 2);
    $result[$key] = $value; 
}

echo(var_dump($result));

/*
> Output: array(8) { 
              ["Hauteur"]=> string(6) "175 cm" 
              ["Height"]=> string(5) "5'9''" 
              ["00010/--/Buste (Femme)"]=> string(5) "92 cm" 
              ["Bust (Women)"]=> string(4) "36''" 
              ["00020/--/Taille"]=> string(5) "74 cm" 
              ["Waist"]=> string(4) "29''" 
              ["00022/--/Hanches"]=> string(5) "99 cm" 
              ["Hips"]=> string(2) "39" 
          }
*/
?>

Please note that this method will only work properly for arrays with an EVEN amount of entries.

davidroseboom
  • 187
  • 10