0

I've been wrapping my head around this for a couple of days...

I have several arrays that need to be sort of merged into a single array. The order in which they merge is of great importance and is simply the order in which they appear in the global array (like the example below):

$input1 = array(
  array(
    'context' => 'aa', 'id' => 1, 'view' => 1, 'update' => 1,
  ),
  array(
    'context' => 'bb', 'id' => 2, 'view' => 0, 'update' => 0,
  )
);
$input2 = array(
  array(
    'context' => 'cc', 'id' => 3, 'view' => 0, 'update' => 1,
  ),
  array(
    'context' => 'dd', 'id' => 4, 'view' => 0, 'update' => 0,
  ),
  array(
    'context' => 'ee', 'id' => 5, 'view' => 1, 'update' => 0,
  )
);
$input3 = array(
  array(
    'context' => 'ff', 'id' => 6, 'view' => 1, 'update' => 1,
  ),
  array(
    'context' => 'gg', 'id' => 7, 'view' => 1, 'update' => 0,
  ),
);

$global = array($input1, $input2, $input3);

Each input array itself consists of several subarrays that are of equal structure; see http://pastebin.com/fQMUjUpB for an example. This pastebin code also includes the desired output. The output array should contain:

  • a single level array
  • a tree-like passthrough upon "merging the next input array", viz. every possible cross-combination of subarrays should be made during a merge between two input arrays
  • the key of each a combination should be generated as a concatenated string of the corresponding context and id elements (glued with a plus) joined together with an ampersand (&); e.g: context1+id1&context2+id2
  • For the next merge the previous resulting array should be used in order for the example from above becomes context1+id1&context2+id2&context3+id3
  • The resulting viewand update elements are calculated by simply multiplying their corresponding values during merge.
$output = array(
  'aa+1&cc+3&ff+6' => array('view' => 0, 'update' => 1),
  'aa+1&cc+3&gg+7' => array('view' => 0, 'update' => 0),
  'aa+1&dd+4&ff+6' => array('view' => 0, 'update' => 0),
  'aa+1&dd+4&gg+7' => array(...),
  'aa+1&ee+5&ff+6' => array(...),
  'aa+1&ee+5&gg+7' => array(...),
  'bb+2&cc+3&ff+6' => array(...),
  'bb+2&cc+3&gg+7' => array(...),
  'bb+2&dd+4&ff+6' => array(...),
  'bb+2&dd+4&gg+7' => array(...),
  'bb+2&ee+5&ff+6' => array(...),
  'bb+2&ee+5&gg+7' => array(...)
);

How can this be accomplished when looping over $global?

I may have expressed myself quite vaguely (it's really hard to explain!), but hopefully it becomes more clear when you take a look at the pastebin code...

Any help would be greatly appreciated!

7
  • You'll never have more than 3 input arrays into the $global array? Commented Nov 8, 2014 at 20:39
  • which algorithm are you use to get that index(like 'aa+1&cc+3&ff+6') in output array ? Commented Nov 8, 2014 at 20:41
  • @Maxime the number of input arrays in $global is varying Commented Nov 8, 2014 at 20:46
  • @fasM For every cross-combination you make, always take context and id of a subarray, combine them with a plus sign and then concatenate it with the (existing) key of the resulting output array by using an ampersand. Commented Nov 8, 2014 at 20:48
  • @fasM those values are the result of multiplication of each subarray merge. So in the case of aa cc gg, then let's say for view it would be $aa['view'] * $cc['view'] * $gg['view'] Commented Nov 8, 2014 at 21:13

1 Answer 1

2

Here's a minimal working code so that you can get the general idea (if you want to improve the code, feel free, there's a lot to do!):

function generate_output($globalArray, $context = array(), $view = 1, $update = 1, &$output = array()) {
    if(!count($globalArray)) {
        $output[implode('&', $context)] = array('view' => $view, 'update' => $update);
    }
    else {
        foreach(reset($globalArray) as $elt) {
            $newContext = $context;
            $newContext[] = $elt['context'] . '+' . $elt['id'];
            generate_output(array_slice($globalArray, 1), $newContext, $view * $elt['view'], $update * $elt['update'], $output);
        }
    }
    return $output;
}

generate_output($global);
Sign up to request clarification or add additional context in comments.

5 Comments

Done. I made some minor changes to your answer to generalize it even more.
Thanks! Indeed, using a global variable is very ugly :)
Another review is pending; instead of $globalArray[0] I suggested using reset($globalArray) to generalize the use case.
Upon taking another look at the code, what's the point of using $newContext = array_slice($context, 0); instead of $newContext = $context;?
There's no point, it's plain stupid. In PHP, arrays are assigned by copy anyway. Both expressions do the same thing, and $newContext = $context; is shorter and clearer. Go for it! I guess I just did a copy & paste from array_slice($globalArray, 1) without thinking much.

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.