4

I am trying to generate a multidimensional array, with a depth equal to the number of matches found in a regular expression. The array keys to be the string value of each match.

For example:

preg_match('/([A-Z])\-?([0-9])\-?([0-9]{1,3})/i', 'A-1-001', $matches);

Returns:

Array (
   [0] => A-1-001
   [1] => A
   [2] => 1
   [3] => 001
)

Which I want to convert to:

$foo = array(
    'A' => array(
        '1' => array(
            '001' => array('some', 'information')
        )
    )
);

So that I can merge it with another multidimensional array like this:

$bar['A']['1']['001'] = array('some', 'other', 'information');

The process needs to handle any number of matches/dimensions.


Below is my current approach. I'm failing to grasp the concept, because this attempt falls way short of my goal.

$foo = array();
$j = count($matches);

for ($i = 1; $i < $j; $i++) {
    $foo[ $matches[$i - 1] ] = $matches[$i];
}

/*
  $foo's structure becomes:
  Array (
      [A-1-001] => A
      [A] => 1
      [1] => 001
  )
*/

It's only swapping array keys, and not creating new children arrays I need.


Any suggestions or solutions would be greatly appreciated. Thanks!

4 Answers 4

2

With some PHP-Fu:

$matches = array('A-1-001', 'A', 1, '001');
$info = array('some', 'information');
print_r(tree($matches, $info));

function tree($array, $info){
    $max = count($array)-1;
    $result = array($array[$max] => $info);
    for($i=$max-1;$i>0;$result = array($array[$i--] => $result));
    return $result;
}

Output:

Array
(
    [A] => Array
        (
            [1] => Array
                (
                    [001] => Array
                        (
                            [0] => some
                            [1] => information
                        )

                )

        )

)
Sign up to request clarification or add additional context in comments.

1 Comment

These are all viable options, though my profiler says HamZa's function executes slightly faster. Thanks for your help, everyone!
1

Well this could be done in a couple of ways, use of recursion for example. Now I had an other idea in my head. You flip the array with array_reverse. This way we can build from the back to the front.

And then we can setup everything. So the code would be something as followed

$foo = array();
$reversed = array_reverse($matches);
$some_info_array = array('some', 'information');

foreach($reversed as $key) {
    if(empty($foo)) {
        $foo[$key] = $some_info_array;
    } else {
        $foo[$key] = $foo;
    }
}

code not tested but should give you a nive idea/start

Comments

1

Given the original array:

$original_array = array( 'A-1-001', 'A', '1', '001' );

You can convert it to the format you described like this:

$new_array[ $original_array[1] ] = array( $original_array[2] => $original_array[3] );

This yields

array(1) {
  ["A"]=>
  array(1) {
    [1]=>
    string(3) "001"
  }
}

You can then assign values to that array as you indicated:

 $new_array['A']['1']['001'] = array('some', 'information');

Comments

1

You could use a function like this ... it should cover any depth. Bonus is that you can keep passing the value of $tree to more branches and get a single tree with multiple products.

function arrayToTree($array, &$tree, $addlAttribs){
    $node = array_shift($array);
    if (count($array)){
        // this is a branch
        $tree[$node] = array();
        return arrayToTree($array, $tree[$node]);
    } else {
        $tree[$node] = $addlAttribs;
        return;
    }
}

You would use it like

$t = array();
array_shift($matches); // remove the first match "A-1-001"
arrayToTree($matches, $tree, $productInfo);
print_r($tree);

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.