2

I need to combine the keys from an array, with the values in another array:

$a = array(4=>2000,5=>5000,7=>1000,3=>5000);
$b = arrray(array(0=>0,1=>4,2=>10,3=>1000),array()...)

This is what I've written (not working):

$keys = array_keys($a);
foreach ($b as $k => $v) {
array_combine($keys,$v);
}

What I expect to get is:

$c = array(array(4=>0,5=>4,7=>10,3=>1000),array(4=>...));
0

3 Answers 3

3

Your code is nearly spot on:

$final=array();
$keys = array_keys($a);
foreach ($b as $v) {
  $final[]=array_combine($keys,$v);
}
Sign up to request clarification or add additional context in comments.

Comments

2

As you need to run the same function on each element of the $b array:

$a = array(4=>2000,5=>5000,7=>1000,3=>5000);
$b = array(array(0,4,10,1000), array(0,4,10,40));

you can make use of array_map with a callback function. The callback function then makes use of array_combine to assign your keys to the values.

As array_combine needs to have the keys to operate but the callback has only the values as input, I created a function that creates the actual callback function based on an array which keys will be taken for the array_combine operation.

As arrays can contain any values, some precautions are done. Empty arrays will not be processed at all, missing values for specific keys will be signalled as NULL:

$keyed = function($array)
{
    $keys = array_keys($array);

    // no keys, nothing to combine
    if (!$len = count($keys)) {
        return function($v) {return array();}; 
    }

    // default values are all NULL
    $pad = array_fill(0, $len, NULL);
    return function($values) use ($keys, $pad, $len)
    {
        // if input is not array, make it an empty array
        !is_array($values) && $values = array();
        return array_combine($keys, array_slice($values + $pad, 0, $len));
    };
};

The $keyed is now an anonymous function that will return the callback function for array_map depending on it's input parameter for array keys:

$c = array_map($keyed($a), $b);

Anonymous functions are available in PHP since version 5.3.

Output:

array(2) {
  [0]=> array(4) {
    [4]=> int(0)
    [5]=> int(4)
    [7]=> int(10)
    [3]=> int(1000)
  }
  [1]=> array(4) {
    [4]=> int(0)
    [5]=> int(4)
    [7]=> int(10)
    [3]=> int(40)
  }
}

Comments

1

Since b has multiple arrays in it, you will just need to do a simple iteration of b:

$a = array(4=>2000,5=>5000,7=>1000,3=>5000);
$b = array(array(0=>0,1=>4,2=>10,3=>1000), array(0=>0,1=>4,2=>10,3=>1000));

$keys = array_keys($a);
$length = count($keys);
$c = array();
foreach($b as $sub) {
    if(!is_array($sub)) {
        $sub = array();
    }

    $c[] = array_combine(array_pad($keys, count($sub), NULL), array_pad(array_values($sub), $length, NULL)); // Pad removes the possibility of a warning
}

print_r($c);

You had the right idea with array_keys($a) and array_combine(). The other argument you needed to feet into array_combine() is the values, array_values($b). But since there are multiple arrays in b, you need to loop through each. As a failsafe in case there are more or less key/value pairs in a or any of the sub-arrays of b, I have added array_pad() to make sure that the two arrays passed in to array_combine() are of equal length so that PHP doesn't complain.

2 Comments

It's missing the edge case that $sub is not an array (if you want to prevent warnings that complete). Additionally I suggest you pad the array with NULL values instead of 0. I've used an anonymous callback function to make the keys part of the callback. This allows as well to use it on any value. See my answer.
@hakre I assumed it was implied that $sub would always be an array, but that could easily be accommodated for if it wasn't (although I do like your callbacks).

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.