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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.