0

I have an array wich is structured like this

  • foo = stuff we don't care for this example
  • foo1_value
  • foo1_label
  • foo1_unit
  • foo2_value
  • foo3_label
  • foo3_value

Can you figure out a fast way to make it look like that ?

  • foo
  • foo1
    • value
    • label
    • unit
  • foo2
    • value
  • foo3
    • value
    • label

I'm actually trying with something like this :

array_walk($array, function($val, $key) use(&$nice_array) {
        $match = false;
        preg_match("/_label|_value|_unit|_libelle/", $key, $match);
        if (count($match)) {
            list($name, $subName) = explode('_', $key);
            $nice_array[$name][$subName] = $val;
        } else {
            $nice_array[$key] = $val;
        }
    });


    echo '<pre>';
    print_r($nice_array);
    echo '</pre>';

This is working I'll just have to reflect on the foo_foo_label thing and it's all good

Su4p
  • 865
  • 10
  • 24
  • What about `date` and `date_modif`? – gen_Eric May 28 '14 at 14:51
  • If this isn't going to get too recursive it might be worth looking at the comments in the PHP documentation for `preg_grep` - especially on matching the keys : http://www.php.net/manual/en/function.preg-grep.php – CD001 May 28 '14 at 14:52
  • `array_walk` does not allow you to add, unset or change the order of the array – danjam May 28 '14 at 15:44
  • @danjam and it's quite normal. But as unseting all the values was fine I tought what if ... and no :( – Su4p May 28 '14 at 15:54

3 Answers3

3

You could use explode on the array keys, something like this:

$newArray = array();
foreach ( $array as $key => $value )
{
    $parts = explode('_', $key);
    $newArray[$parts[0]][$parts[1]] = $value; 
}

Edit: update as detailed in comments. Will handle your foo_foo_value case as well as foo and foo_foo. There's really no reason to use array_walk if you're only passing the results off to a second array.

$newArray = array();
foreach ( $array as $key => $value ) {
  if ( preg_match('/_(label|value|unit)$/', $key) === 0 ) {
    $newArray[$key] = $value;
    continue;
  }
  $pos = strrpos($key, '_');
  $newArray[substr($key, 0, $pos)][substr($key, $pos+1, strlen($key))] = $value;
}
danjam
  • 1,064
  • 9
  • 13
  • *Note* The array's keys must be in the following format: `xxx_yyy`. – Ofir Baruch May 28 '14 at 14:57
  • this was my intial tought but I think php has a more elegant way to deal with this – Su4p May 28 '14 at 14:57
  • @OfirBaruch Very true, just noticed OP has a key not in that format. – danjam May 28 '14 at 15:04
  • @Su4p do you want to disregard those elements entirely or must they stay the same? – danjam May 28 '14 at 15:04
  • @danjam the problem with this method is what if I have foo_foo_value. – Su4p May 28 '14 at 15:07
  • @danjam with an array_walk function ;) – Su4p May 28 '14 at 15:07
  • In fact I prefer to explode only on _label _unit _value this part will stay unflexible cause the foo part can be tricky has I told – Su4p May 28 '14 at 15:09
  • Yes, it does get a bit more involved if you array key format varies greatly. My method is only really aimed at the format you specified – danjam May 28 '14 at 15:10
  • I just like the array_map/array_walk functions but you're right. Finaly I took you version. Mine works too btw. http://leve.rs/blog/benchmark-analysis-of-php-array-loops/ – Su4p May 30 '14 at 12:49
  • Thanks for that link, interesting results and I completely agree with the conclusion. The main thing is that you were able to solve your problem, whichever method you choose to use :) – danjam May 30 '14 at 13:20
0

What you can do is loop over the array, and split (explode()) each key on _ to build your new array.

$newArray = array();
foreach($oldArray as $key=>$value){
    list($name, $subName) = explode('_', $key);

    if($subName !== NULL){
        if(!isset($newArray[$name])){
            $newArray[$name] = array();
        }
        $newArray[$name][$subName] = $value;
    }
    else{
        $newArray[$name] = $value;
    }
}
gen_Eric
  • 223,194
  • 41
  • 299
  • 337
0
    $nice_array = array();
    array_walk($array, function($val, $key) use(&$nice_array) {
        $match = false;
        preg_match("/_label|_value|_unit|_libelle/", $key, $match);
        if (count($match)) {
            $tname = preg_split("/_label$|_value$|_unit$|_libelle$/",$key);
            $name = $tname[0];
            $subName = substr($match[0],1);
            $nice_array[$name][$subName] = $val;
        } else {
            $nice_array[$key] = $val;
        }
    });
Su4p
  • 865
  • 10
  • 24