Reputation: 960
I have
$map = array('id' => 'clmId', 'name' => 'clmName' => 'value' => 'clmValue',);
$value = array('id' => 1, 'name' => 'Foo', 'value' => 'Bar',);
and I want to get
$expected = array('clmId' => 1, 'clmName' => 'Foo', 'clmValue' => 'Bar');
of course I did $expected = array_combine($map, $value)
and it works most of the time, but fails (to my surprise) for following
$map = array('id' => 'clmId', 'name' => 'clmName' => 'value' => 'clmValue',);
$value = array('name' => 'Foo', 'id' => 1, 'value' => 'Bar',);
$expected = array_combine($map, $value);
//you get
//$expected = array('clmId' => Foo, 'clmName' => 1, 'clmValue' => 'Bar');
clearly, array_combine
is not meant for combining associative arrays. What can be done to achieve this ?
I am doing a primitive foreach($map as $key => $mapValue) { ...
but I am guessing a smarter map/reduce or some cool array function should do it for me.
Return array()
/FALSE
in case $value
has no corresponding key from $map
Upvotes: 1
Views: 3282
Reputation: 26467
function combine_if_same_keys( $array_one, $array_two ) {
$expected = false;
ksort($array_one);
ksort($array_two);
$diff = array_diff_key($array_one, $array_two);
if( empty($diff) && count($array_one) == count($array_two) ) {
$expected = array_combine( $array_one, $array_two );
}
return $expected;
}
Returns false if the keys don't match and an array if they did match.
$map = array('id' => 'clmId', 'name' => 'clmName', 'value' => 'clmValue');
$value = array('id' => 1, 'name' => 'Foo', 'value' => 'Bar');
$value2 = array('ids' => 1, 'name' => 'Foo', 'value' => 'Bar');
var_dump( combine_if_same_keys( $map, $value ) );
var_dump( combine_if_same_keys( $map, $value2 ) );
Outputs:
array(3) { ["clmId"]=> int(1) ["clmName"]=> string(3) "Foo" ["clmValue"]=> string(3) "Bar" }
bool(false)
Edit: Benchmarking
Just read some comments on another answer which suggested that ksort()
will cause a performance hit, so I did a bit of benchmarking Ran ksort()
on 2 arrays with (albeit numeric keyed arrays) 10,000,000 keys each which only took 0.010757923126221 seconds on
Intel Q8200 @ 2.33ghz (4CPUs), 3072MB RAM, Windows 7 x64 .
Edit (by OP): Number of keys should match as well
array_diff_key($a1, $a2)
returns empty array even if count($a2) > count($a1)
, the array_combine
returns FALSE while generating a warning.
One can suppress it by @array_combine
, but I would rather put the count condition (along with the appropriate empty() test on the array_key_diff
return) and then combine the array.
Upvotes: 4
Reputation: 265231
I think there is no builtin way
function combine_assoc($map, $values) {
$output = array();
foreach($map as $key => $values) {
if(!array_key_exists($key, $value)) return FALSE;
$output[$value] = $values[$key];
}
return $output;
}
Of course, you could simply sort your arrays by key first, but this does not take care of missing key/value pairs and has a somewhat decreased performance:
ksort($map);
ksort($value);
$output = array_combine($map, $value);
Version without foreach loop, which does check for matching keys, but I do not recommend it, since it will not perform well …
function combine_assoc_slow($map, $value) {
ksort($map);
ksort($value);
if(array_keys($map) != array_keys($value)) return FALSE;
return array_combine($map, $value);
}
Upvotes: 2
Reputation: 13843
So array_combine
doesn't work if the order is different? Well, easiest solution for you: sorting both arrays by key!
$map = array('id' => 'clmId', 'name' => 'clmName' => 'value' => 'clmValue');
$value = array('name' => 'Foo', 'id' => 1, 'value' => 'Bar');
ksort($map);
ksort($value);
// keys are "aligned", ready to combine
$expected = array_combine($map, $value);
Upvotes: 0