Reputation: 7788
I have two arrays which must be merged together on the dt_date
column and I need to declare subscribers
and unsubscribers
in all rows in the result.
$array1 = [
['subscribers' => 2, 'dt_date' => '2014-02-27'],
['subscribers' => 2, 'dt_date' => '2014-02-25'],
['subscribers' => 1, 'dt_date' => '2014-02-07']
];
$array2 = [
['unsubscribers' => 1, 'dt_date' => '2014-02-27'],
['unsubscribers' => 1, 'dt_date' => '2014-02-01']
];
I need to create an array like as follows from the two arrays.
[
['subscribers' => 2, 'unsubscribers' => 1, 'dt_date' => '2014-02-27'],
['subscribers' => 2, 'unsubscribers' => 0, 'dt_date' => '2014-02-25'],
['subscribers' => 1, 'unsubscribers' => 0, 'dt_date' => '2014-02-07'],
['subscribers' => 0, 'unsubscribers' => 1, 'dt_date' => '2014-02-01']
]
I tried
$result = array_merge_recursive($aray1, $array2);
AND
$result = array_merge(
$array1,
array_udiff(
$array2,
$array1,
function($array1,$array2){
return strcmp($array1['dt_date'],$array2['dt_date']);
}
)
);
But the result was not as expected
Upvotes: 0
Views: 130
Reputation: 48073
array_values()
(this removes the temporary first level keys).Code: (Demo)
$result = [];
$default = array_fill_keys(['subscribers', 'unsubscribers'], 0);
foreach (array_merge($array1, $array2) as $row) {
$result[$row['dt_date']] = array_merge($result[$row['dt_date']] ?? $default, $row);
}
var_export(array_values($result));
The functional-style equivalent: (Demo)
$default = array_fill_keys(['subscribers', 'unsubscribers'], 0);
var_export(
array_values(
array_reduce(
array_merge($array1, $array2),
function($result, $row) use($default) {
$result[$row['dt_date']] = array_merge($result[$row['dt_date']] ?? $default, $row);
return $result;
}
)
)
);
Upvotes: 0
Reputation: 7788
I find the answer
$result= array_replace_recursive($array1,$array2);
foreach ($result as $key => $value) {
if(!isset($value['unsubscribers']))
$result[$key]['unsubscribers']=0;
if(!isset($value['subscribers']))
$result[$key]['subscribers']=0;
}
Thank you
Upvotes: 0
Reputation: 37365
Actually, your question can be resolved with some foreach
stuff, but I've noticed that you're trying to emulate some kind of SQL JOIN
behavior (with ON
column as dt_date
). That's why I've spent some more time and created more common solution.
First, we'll need to re-index our arrays so we could work with them faster:
function reindexArray($array, $column)
{
return array_combine(
array_map(function($x) use ($column)
{
return $x[$column];
}, $array),
$array
);
}
Function above could be easily replaced with array_column()
call, but I assume you have PHP 5.3, thus you'll need "manual" re-indexing.
Next, join logic:
function arrayJoin($array1, $array2, $column, $default=null)
{
//in PHP 5.5 it's just array_column() call:
$array1 = reindexArray($array1, $column);
$array2 = reindexArray($array2, $column);
$blank1 = array_combine(
array_keys(current($array1)),
array_fill(1, count(current($array1)), $default)
);
$blank2 = array_combine(
array_keys(current($array2)),
array_fill(1, count(current($array2)), $default)
);
unset($blank1[$column], $blank2[$column]);
return array_merge(
array_map(function($x) use ($array1, $blank2)
{
return array_merge($array1[$x], $blank2);
}, array_keys(array_diff_key($array1, $array2))),
array_map(function($x) use ($array1, $array2)
{
return array_merge($array1[$x], $array2[$x]);
}, array_keys(array_intersect_key($array1, $array2))),
array_map(function($x) use ($array2, $blank1)
{
return array_merge($array2[$x], $blank1);
}, array_keys(array_diff_key($array2, $array1)))
);
}
-as you can see, you'll also need to decide what to do with non-set keys for each joined array. $default
will fill that values for you. Therefore, your question would be resolved via:
$result = arrayJoin($array1, $array2, 'dt_date', 0);
-check this demo.
However, if your original array is derived from some SQL database, much better thing would be to place JOIN
logic there - because intention of DB is to store data & select it properly.
Upvotes: 1