0

I need help with php array merging

I need merge by values,

so if I have values in array 1 like this

 ( room room )  and in array values  ( room ) , merge will look like this =  ( room room ) 

But if I have

 ( room room book ) and ( book book ) merged array values will look like this  ( room room book book ) 

So lets say, merged array values will be maximum count of each element, room for example , in all arrays

Few more examples, ( book ) ( book ) ( book ) = ( book ) ( room book book ) ( library room ) = ( library room book book ) ( room room ) ( book book book ) = ( room room book book book ) (room) ( room ) ( room room room ) = ( room room room )

I tried operator + , but then

( room room ) ( book book book ) is ( room room book book ), that is not good

I tried array_merge , but then

( room ) ( room ) is ( room ) , this is okay but ( room room ) ( room ) is ( room room room ) and that is wrong

It doesnt depend on order, and keys are not imporant, it is always numeric ( [0] [1] etc. )

ARRAYS :

                [0] => Array
                    (
                        [0] => room
                        [1] => room
                    )

                [1] => Array
                    (
                        [0] => book
                        [1] => book
                        [2] => book
                        [3] => book
                    )

EXPECTED RESULT = array ( room, room, book , book , book, book )

                [0] => Array
                    (
                        [0] => room
                        [1] => room
                    )

                [1] => Array
                    (
                        [0] => room
                    )

EXPECTED RESULT = array ( room, room )

                [0] => Array
                    (
                        [0] => room
                    )

                [1] => Array
                    (
                        [0] => room


                    )

EXPECTED RESULT = array ( room )

                [0] => Array
                    (
                        [0] => room
                        [1] => room
                        [2] => book
                    )

                [1] => Array
                    (
                        [0] => room
                        [1] => book
                    )
                [2] => Array
                    (
                        [0] => room
                        [1] => room
                        [2] => room
                    )

EXPECTED RESULT = array ( room , room ,room , book )

So it is alway maximum count of each ellement, for example book in all arrays

Thank you very much,

Marek

1
  • 2
    Your array notation is not very readable. Can you include the print_r() outputs of your arrays, so it's easier for us to see the contents of the array? Commented Mar 12, 2014 at 16:02

2 Answers 2

1

Here it is:

function user_array_merge($arr) {
  if (func_num_args() == 1) return $arr;
  $vals = array_count_values($arr);
  $arrs = func_get_args();
  array_shift($arrs);
      foreach ($arrs as $arr2) {
        $vals2 = array_count_values($arr2);
        foreach ($vals2 as $val=>$count) {
           $vals[$val] = @max( $vals[$val], $count);
        }
      }
      $result = array();
      foreach ($vals as $val=>$count) {
         $result = array_pad($result, count($result)+$count, $val);
      }
      return $result;
    }

call like:

$res = user_array_merge(['room','room'], ['book', 'book','book','room'],['library']);

result:

var_export($res);                                                                                    
array (
  0 => 'room',
  1 => 'room',
  2 => 'book',
  3 => 'book',
  4 => 'book',
  5 => 'library',
)

Should be quite slow on large arrays.

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

1 Comment

+1, this is the first time I see the incremental generation with array_pad trick. Not tested, but it seems like it would be the most performant way to build up the results array. Nice!
0

This would be a reasonable way to do it in O(n):

function custom_array_merge() {
    // variable number of inputs
    $arrays = func_get_args();

    // consolidate into array of items => count/array(of counts) across inputs
    $counts = array_map('array_count_values', $arrays);
    $consolidated = call_user_func_array('array_merge_recursive', $counts);

    // reduce array of counts (where applicable) to maximum count
    $maximums = array_map(function($v) { 
        return is_array($v) ? max($v) : $v;
    }, $consolidated);

    // build result -- could be faster with array_fill() and concatenating 
    // but that would definitely use up more memory 
    $result = [];
    foreach ($maximums as $item => $times) {
        for ($i = 0; $i < $times; ++$i) {
            $result[] = $item;
        }
    }

    return $result;
}

See it in action.

3 Comments

I tried to use it, but I've got this warning. Warning: array_merge_recursive() expects at least 1 parameter, 0 given in $counts = array_map('array_count_values', $deti); $consolidated=call_user_func_array('array_merge_recursive',$counts); and $counts is printed correctly
@user3411282: how do you call it? Post an example on ideone.
@user3411282: It looks like you have a mistake in the code somewhere. Please post your exact code so that it runs and prints the warning.

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.