I have two arrays like this :
Array1
Array
(
[0] => Array
(
[ID] => 101
[Code] => 1075
[Date] => 2012-03-03 17:13:12.433
)
[1] => Array
(
[ID] => 103
[Code] => 175
[Date] => 2012-09-05 20:30:02.217
)
[2] => Array
(
[ID] => 109
[Code] => 178
[Date] => 2012-07-05 20:30:02.217
)
)
Array2
Array
(
[0] => Array
(
[Amount] => 1234
[ID] => 101
)
[1] => Array
(
[Amount] => 1342
[ID] => 103
)
[2] => Array
(
[Amount] => 0
[ID] => 0
)
)
I use this code to combine them based on the matching values of the ID index.
$combined = array();
foreach ($arr as $arrs) {
$comb = array('ID' => $arrs['ID'], 'Code' => $arrs['Code'],'Date' => $arrs['Date'],'Amount' => '');
foreach ($arr4 as $arr2) {
if ($arr2['ID'] == $arrs['ID']) {
$comb['Amount'] = $arr2['Amount'];
break;
}
else {
$comb['Amount'] = $arr2['Amount'];
}
}
$combined[] = $comb;
}
echo print_r($combined);
And here is the desired output I get from this code :
Array
(
[0] => Array
(
[ID] => 101
[Code] => 1075
[Date] => 2012-03-03 17:13:12.433
[Amount] => 1234
)
[1] => Array
(
[ID] => 103
[Code] => 175
[Date] => 2012-09-05 20:30:02.217
[Amount] => 1342
)
[2] => Array
(
[ID] => 109
[Code] => 178
[Date] => 2012-07-05 20:30:02.217
[Amount] => 0
)
)
I want to optimize the code such that
$comb = array('ID' => $arrs['ID'], 'Code' => $arrs['Code'],'Date' => $arrs['Date'],'Amount' => '');
should be generated dynamically rather than hard coded.
And instead of $comb['Amount'] = $arr2['Amount'];
I want code to automatically add all the other feilds to the first array where the ID matches.
How do I achieve this?
Simplest solution to make it completely dynamic apart from ID
, do like below:
$arr2 = array_column($array2, "ID");
$finalArray = array();
foreach($array1 as $arr){
$key = array_search($arr['ID'], $arr2);
if($key ===false){
$key = array_search(0, $arr2);
}
unset($array2[$key]['ID']);
$finalArray[] = array_merge($arr,$array2[$key]);
}
print_r($finalArray);
Output:- https://3v4l.org/1sDJs
First use the ID as keys:
$arr1 = array_column($arr1, null, "ID");
$arr2 = array_column($arr2, null, "ID");
Then sort the key (to solve non-same original indexes:
ksort($arr1);
ksort($arr2);
Then use array_map
as:
$res = array_map('array_merge', $arr1, $arr2);
Use array_values
at the end to ignore the ID keys.
And if you have another array that include the ID field you can have the same logic on them - notice array_map
can get more then 2 input array...
Reference: array_column, array_map, array_merge, ksort
Live example: 3v4l
Edited:
Used template to fix issue where element are missing:
$keys = array_merge(array_keys($a[0]), array_keys($b[0]));
$template = array_combine($keys, array_fill(0, count($keys), null)); // create array of null for all keys
$a = array_column($a, null, "ID");
$b = array_column($b, null, "ID");
ksort($a);
ksort($b);
$res = array_map(function ($e1, $e2) use ($template){
if ($e1 && $e2) return array_merge($e1, $e2); // if exist merge
$e = $e1 ? $e1 : $e2; //get the exist element
return array_replace ($template, $e); // add it
}, $a, $b);
Notice this solution will be valid to only 2 array - it can be generalize but I leave that to you
Live example: 3v4l
I tweak your code to do what you need, here is the complete code that worked for me:
<?php
$arr=Array(
Array("ID" => 101, "Code" => 1075, "Date" => "2012-03-03 17:13:12.433"),
Array("ID" => 103, "Code" => 175, "Date" => "2013-03-03 17:13:12.433"),
Array("ID" => 109, "Code" => 178, "Date" => "2014-03-03 17:13:12.433")
);
$arr4 = Array(
Array("ID" => 101, "Amount" => 1234),
Array("ID" => 103, "Amount" => 1342),
Array("ID" => 0, "Amount" => 0)
);
$combined = array();
foreach ($arr as $i => $arrs) {
$combined['ID'][$i] = $arrs['ID'];
$combined['Code'][$i] = $arrs['Code'];
$combined['Date'][$i] = $arrs['Date'];
foreach ($arr4 as $arr2) {
if ($arr2['ID'] == $arrs['ID']) {
$combined['Amount'][$i] = $arr2['Amount'];
break;
}
}
if (!isset($combined['Amount'][$i])) {
$combined['Amount'][] = 0;
}
}
echo print_r($combined);
?>
If you need further manipulation for different reasons, i suggest you read about array_keys
and array_values
methods, which are very helpful.
$firstArray = [
[
'ID' => 101,
'Code' => 1075,
'Date' => '2012-03-03 17:13:12.433',
],
[
'ID' => 103,
'Code' => 175,
'Date' => '2012-09-05 20:30:02.217',
],
[
'ID' => 109,
'Code' => 178,
'Date' => '2012-07-05 20:30:02.217',
],
];
$secondArray = [
[
'ID' => 101,
'Amount' => 1234,
],
[
'ID' => 103,
'Amount' => 1342,
],
[
'ID' => 0,
'Amount' => 0,
],
];
class DTO implements \Serializable
{
/** @var int */
private $id;
/** @var int */
private $code;
/** @var string */
private $date;
/** @var int */
private $amount = 0;
/**
* {@inheritDoc}
*/
public function serialize()
{
return [
'ID' => $this->id,
'Code' => $this->code,
'Date' => $this->date,
'Amount' => $this->amount,
];
}
/**
* {@inheritDoc}
*
* @param array $serialized
*/
public function unserialize($serialized): self
{
$this->id = $serialized['ID'];
$this->code = $serialized['Code'];
$this->date = $serialized['Date'];
$this->amount = $serialized['Amount'] ?? 0;
return $this;
}
}
$thirdArray = [];
foreach ($secondArray as $item) {
$id = $item['ID'];
unset($item['ID']);
$thirdArray[$id] = $item;
}
$thirdArrayKeys = array_keys($thirdArray);
foreach ($firstArray as &$item) {
$id = $item['ID'];
$dto = new DTO();
$dto->unserialize($item);
if (in_array($id, $thirdArrayKeys)) {
$dto = $dto->unserialize(array_merge($item, $thirdArray[$id]));
}
$item = $dto->serialize();
}
http://sandbox.onlinephpfunctions.com/code/ee72a1c89782f4eef25a1143816f237ca6af129c
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With