Merge first array particular key and value into second array - php

I have 2 array
$arr1 = Array (
[0] => Array ( [customer_id] => 1 [Expire] => 2019-05-14 [paid] => 1 )
[1] => Array ( [customer_id] => 2 [Expire] => 2019-06-20 [paid] => 0 ))
and
$arr2 = Array (
[0] => Array ( [id] => 3943 [customer_id] => 1 [Expire] => 2019-05-14 )
[1] => Array ( [id] => 3944 [customer_id] => 1[Expire] => 2019-05-14 )
[2] => Array ( [id] => 4713 [customer_id] => 2 [Expire] => 2019-06-20 )
)
and try to put first array key and value [paid]=>1 or 0 in second array if customer id and expire match like
Array (
[0] => Array ( [id] => 3943 [customer_id] => 1 [Expire] => 2019-05-14 [paid] => 1)
[1] => Array ( [id] => 3944 [customer_id] => 1 [Expire] => 2019-05-14 [paid] => 1)
[2] => Array ( [id] => 4713 [customer_id] => 2 [Expire] => 2019-06-20 [paid] => 0)
)
I try to merge array in php but not get exact what i want. Is there any php function to do it?.

Loop your second array $arr2, and find the index of the first array $arr1 where the column customer_id is the same as in the current iteration of $arr2. array_search() returns that index, which we can then use to fetch the paid index of that array. Then we append it to our array $arr2, by doing $a['paid'] = $paid;.
Since we loop the array by reference (the & before $a in the loop), the changes we make to it, will be applied back to the original array.
foreach ($arr2 as &$a) {
$customerID = $a['customer_id']; // This customer ID
$arr1_key = array_search($customerID, array_column($arr1, 'customer_id')); // Find the index of this customerID in the first array
$paid = $arr1[$arr1_key]['paid']; // Find the paid value matching that customer ID
$a['paid'] = $paid;
}
Live demo at https://3v4l.org/Meqtu
Update
If you need it to match the ID as well as the expiration date, then use array_filter() to fetch the array-element within $arr1 that matches the date and the ID. Using reset(), we use the first element in that array.
foreach ($arr2 as &$a) {
// Find the sub-array of $arr1 that matches this array's date and ID
$arr1_match = array_filter($arr1, function($v) use ($a) {
return $v['customer_id'] == $a['customer_id'] && $v['Expire'] == $a['Expire'];
});
// Get the first element from the result
$paid = reset($arr1_match)['paid'];
// Append the paid-value to this array (done by reference)
$a['paid'] = $paid;
}
Live demo at https://3v4l.org/mov6d

sometimes things can be done in hard way:)
<?php
$arr1 = [
['customer_id' => 1, 'Expire' => '2019-05-14', 'paid' => 1],
['customer_id' => 2, 'Expire' => '2019-06-20', 'paid' => 0],
];
$arr2 = [
['id' => 3943, 'customer_id' => 1, 'Expire' => '2019-05-14'],
['id' => 3944, 'customer_id' => 1, 'Expire' => '2019-05-14'],
['id' => 3945, 'customer_id' => 2, 'Expire' => '2019-05-14'],
['id' => 4713, 'customer_id' => 2, 'Expire' => '2019-06-20'],
];
foreach ($arr2 as &$item2) {
foreach ($arr1 as $item1) {
if (
$item2['customer_id'] === $item1['customer_id']
&& $item2['Expire'] === $item1['Expire']
) {
$item2['paid'] = $item1['paid'];
break;
}
}
}
unset($item2);
var_dump($arr2);

If you cannot change the layout of the first array I think it will be best to first create an intermediate array that keeps a record of all expire dates for every customer.
The following implementation does not require you to use a nested loop.
<?php
$arr1 = [
['customer_id' => 1, 'Expire' => '2019-05-14', 'paid' => 1],
['customer_id' => 2, 'Expire' => '2019-06-20', 'paid' => 0],
];
$arr2 = [
['id' => 3943, 'customer_id' => 1, 'Expire' => '2019-05-14'],
['id' => 3944, 'customer_id' => 1, 'Expire' => '2019-05-14'],
['id' => 3945, 'customer_id' => 2, 'Expire' => '2019-05-14'],
['id' => 4713, 'customer_id' => 2, 'Expire' => '2019-06-20'],
];
// Create a list of all paid, expiry dates, keyed by customer_id
$payed = [];
foreach ($arr1 as $item) {
if (!isset($payed[$item['customer_id']])) {
$payed[$item['customer_id']] = [];
}
$payed[$item['customer_id']][] = $item['Expire'];
}
// Lookup the customer and expire date for every entry
$arr2 = array_map(function($item) use ($payed) {
$item['paid'] = in_array($item['Expire'], $payed[$item['customer_id']] ?? []);
return $item;
}, $arr2);
Result:
Array
(
[0] => Array
(
[id] => 3943
[customer_id] => 1
[Expire] => 2019-05-14
[paid] => 1
)
[1] => Array
(
[id] => 3944
[customer_id] => 1
[Expire] => 2019-05-14
[paid] => 1
)
[2] => Array
(
[id] => 3945
[customer_id] => 2
[Expire] => 2019-05-14
[paid] =>
)
[3] => Array
(
[id] => 4713
[customer_id] => 2
[Expire] => 2019-06-20
[paid] => 1
)
)
See demo

This can fix the issue :
$arr1 = array(
["customer_id"=>1,"Expire"=> "2019-05-14", "paid"=>1],
["customer_id"=>2,"Expire"=> "2019-06-20", "paid"=>0]
);
$arr2 = array(
["id"=>3943, "customer_id"=>1,"Expire"=> "2019-05-14"],
["id"=>3944,"customer_id"=>2,"Expire"=> "2019-06-20"],
["id"=>4713,"customer_id"=>1,"Expire"=> "2019-05-14"]
);
$result= array();
function getRowByCustomerID($id, $array){
foreach($array as $value){
if($value['customer_id'] ==$id){
return $value;
}
}
return null;
}
foreach($arr2 as $subarr){
$object = getRowByCustomerID($subarr['customer_id'],$arr1 );
if(!is_null($object)){
$object['id']=$subarr['id'];
$result[]= $object;
}
}
var_dump($result);
the output is similar to what you are looking for :
array(3) {
[0]=>
array(4) {
["customer_id"]=>
int(1)
["Expire"]=>
string(10) "2019-05-14"
["paid"]=>
int(1)
["id"]=>
int(3943)
}
[1]=>
array(4) {
["customer_id"]=>
int(2)
["Expire"]=>
string(10) "2019-06-20"
["paid"]=>
int(0)
["id"]=>
int(3944)
}
[2]=>
array(4) {
["customer_id"]=>
int(1)
["Expire"]=>
string(10) "2019-05-14"
["paid"]=>
int(1)
["id"]=>
int(4713)
}
}

Related

shift multidimentional array to single array

I want to remove key 0 from parent array and set child array as parent.
Here I will get single value so one array is ok for me.
My current array looks like this
Array
(
[0] => Array
(
[id] => 3
[api_key] => acount266
[auth_domain] => Tester26
[database_url] => vcc.test.acc+27#gmail.com
[project_id] => 12345
[storage_bucket] =>
[secret_key_path] =>
[fcm_server_key] => 1
[messaging_sender_id] => 0
[key_phrase] =>
[disable] => 0
[created] =>
[updated] =>
)
)
I want it like below. expected result
Array
(
[id] => 3
[api_key] => acount266
[auth_domain] => Tester26
[database_url] => vcc.test.acc+27#gmail.com
[project_id] => 12345
[storage_bucket] =>
[secret_key_path] =>
[fcm_server_key] => 1
[messaging_sender_id] => 0
[key_phrase] =>
[disable] => 0
[created] =>
[updated] =>
)
For this I tried like below but no success.
$new = array();
foreach ($data as $v){
$new = array_merge($new , array_values($v)) ;
}
but in my code it's removed key e.g id,api_key, etc....
I need key name also in my new array. please suggest
Remove the array_values
Solution
<?php
$test = array(
array
(
'id' => 3,
'api_key' => 'acount266'
)
);
$new = array();
foreach($test as $v){
$new = array_merge($new, $v);
}
var_dump($new);
Result
array(2) {
["id"]=>
int(3)
["api_key"]=>
string(9) "acount266"
}
According to documentation of PHP as mentioned
reset() function returns the value of the first array element, or
FALSE if the array is empty.
$array = array(
array(
'id' => 3,
'api_key' => 'acount266',
'auth_domain' => 'Tester26',
'database_url' => 'vcc.test.acc+27#gmail.com',
'project_id' => '12345',
'storage_bucket' => '',
'secret_key_path' => '',
'fcm_server_key' => 1,
'messaging_sender_id' => 0,
'key_phrase' => '',
'disable' => 0,
'created' => '',
'updated' => ''
)
);
print_r(reset($test));
I tried this:
$arr = array();
foreach ($examples as $example) {
foreach ($example as $e) {
array_push($arr, $e);
}
}
Don't overcomplicate this, reassigning the first element to the parent array is quick and easy:
<?php
$array =
array (
0 =>
array (
'first' => 'Michael',
'last' => 'Thompson'
)
);
$array = $array[0];
var_export($array);
Output:
array (
'first' => 'Michael',
'last' => 'Thompson',
)
Or:
$array = array_shift($array);

How to replace numeric keys in associative array with their corresponding values

I do have following associative multidimensional array available after json_decode(string, true).
Array
(
[statusCode] => 200
[data] => Array
(
[objects] => Array
(
[0] => deals
[1] => contacts
[2] => accounts
)
[deals] => Array
(
[0] => dealName
[1] => ApprovedBy
[2] => ApprovedDate
[3] => CloseDate
)
[contacts] => Array
(
[0] => contectName
[1] => email
[2] => firstName
[3] => lastName
)
[accounts] => Array
(
[0] => accountName
[1] => creationDate
[2] => ApprovedDate
[3] => accountNumber
)
)
)
It want to replace numeric keys with their corresponding values in arrays like:
[deals] => deals
[contacts] => contacts
[accounts] => accounts
What I tried so far?
$finalIOArray = array();
$integrationObjectsArray = $response['data']['objects'];
foreach($integrationObjectsArray as $integrationObject){
$finalIOArray[$integrationObject] = $integrationObject;
}
This is for only the objects array in the main data array. But I want to replace keys with values in all the sub-arrays in the main data array.
here's a recursive solution to the problem
function updateArray(array $data)
{
$result = array();
foreach ($data as $key => $value) {
if (is_integer($key) && is_string($value)) { // key is integer and value is string
$result[$value] = $value; // update the key
} elseif (is_array($value)) { // value is array
$result[$key] = updateArray($value); // recurse
} else {
$result[$key] = $value; // leave key/value alone
}
}
return $result;
}
print_r(updateArray($arr));
You can do like this
foreach($arr["data"] as $key=>&$data){
$new = array();
foreach($data as $key2=>$value){
$new[$value] = $value;
}
$data = $new;
}
print_r($arr);
Live demo : https://eval.in/858599
I modify my code to suits your needs, please, try it.
$data = [];
foreach($arr["data"] as $key => $example) {
$new = [];
foreach($example as $value) {
$new[$value] = $value;
}
$data[$key] = $new;
}
$arr["data"] = $data;
print_r($arr);
This is a cleaner and more direct method than the others on offer. Use array_combine to bulk reassign keys using values from the subarray.
In my method using foreach, the & before $data means "passing by reference" . http://php.net/manual/en/language.references.pass.php This effectively allows the modification of the original array data without writing the keys that lead to the specific deep element.
Code:
$arr = Array
(
"statusCode" => 200,
"data" => Array
(
"objects" => Array
(
"0" => deals,
"1" => contacts,
"2" => accounts
),
"deals" => Array
(
"0" => dealName,
"1" => ApprovedBy,
"2" => ApprovedDate,
"3" => CloseDate
),
"contacts" => Array
(
"0" => contectName,
"1" => email,
"2" => firstName,
"3" => lastName
),
"accounts" => Array
(
"0" => accountName,
"1" => creationDate,
"2" => ApprovedDate,
"3" => accountNumber
)
)
);
foreach($arr["data"] as &$data){
$data=array_combine($data,$data);
}
var_export($arr);
Output:
array (
'statusCode' => 200,
'data' =>
array (
'objects' =>
array (
'deals' => 'deals',
'contacts' => 'contacts',
'accounts' => 'accounts',
),
'deals' =>
array (
'dealName' => 'dealName',
'ApprovedBy' => 'ApprovedBy',
'ApprovedDate' => 'ApprovedDate',
'CloseDate' => 'CloseDate',
),
'contacts' =>
array (
'contectName' => 'contectName',
'email' => 'email',
'firstName' => 'firstName',
'lastName' => 'lastName',
),
'accounts' =>
array (
'accountName' => 'accountName',
'creationDate' => 'creationDate',
'ApprovedDate' => 'ApprovedDate',
'accountNumber' => 'accountNumber',
),
),
)
Or if you prefer functional iteration, this provides the same output.
$arr["data"]=array_map(function ($a){return array_combine($a,$a);},$arr["data"]);
var_export($arr);

How to extract values from multidimensional array grouped by some value inside it using PHP?

I have an array that looks like this:-
Array (
[0] => Array ( [id] => 10 [group] => 11 )
[1] => Array ( [id] => 11 [group] => 13 )
[2] => Array ( [id] => 12 [group] => 13 )
[3] => Array ( [id] => 13 [group] => 13 )
[4] => Array ( [id] => 14 [group] => 16 )
[5] => Array ( [id] => 15 [group] => 16 )
[6] => Array ( [id] => 16 [group] => 16 )
)
For each different group in this array i want to create array that stores id's.
In my example i have 3 groups, so i want to get 3 arrays like this:
Array ( [0] => 10)
Array ( [0] => 11
[1] => 12
[2] => 13)
Array ( [0] => 14
[1] => 15
[2] => 16)
Is it possible if it is how can i do it?
This should help you get started.
https://iconoun.com/demo/temp_icold.php
<?php // demo/temp_icold.php
/**
* Manipulate multi-dimensional arrays
*
* https://stackoverflow.com/questions/45422046/how-to-extract-values-from-multidimensional-array-grouped-by-some-value-inside-i
*/
error_reporting(E_ALL);
echo '<pre>';
$original = Array (
'0' => Array ( 'id' => 10, 'group' => 11 ),
'1' => Array ( 'id' => 11, 'group' => 13 ),
'2' => Array ( 'id' => 12, 'group' => 13 ),
'3' => Array ( 'id' => 13, 'group' => 13 ),
'4' => Array ( 'id' => 14, 'group' => 16 ),
'5' => Array ( 'id' => 15, 'group' => 16 ),
'6' => Array ( 'id' => 16, 'group' => 16 ),
);
print_r($original);
foreach ($original as $arr)
{
$ndx = 'group' . $arr['group'];
$out[$ndx][] = $arr['id'];
}
print_r($out);
You can achieve this through many different methods, but the simplest is probably a foreach() loop. In the example below I am looping through $a (your sample array) and building up a new array called $grouped with the index as the group attributes value.
In my example I am not duplicating the ID's inside of $group. If you wanted duplicates you could remove the second if statement.
$a = [
['id' => 10, 'group' => 11],
['id' => 11, 'group' => 13],
['id' => 12, 'group' => 13],
['id' => 13, 'group' => 13],
['id' => 14, 'group' => 16],
['id' => 15, 'group' => 16],
['id' => 16, 'group' => 16],
];
$grouped = [];
foreach ($a as $entry) {
if (! array_key_exists($entry['group'], $grouped)) {
$grouped[$entry['group']] = [];
}
if (! in_array($entry['id'], $grouped[$entry['group']])) {
$grouped[$entry['group']][] = $entry['id'];
}
}
var_dump($grouped);
The example outputs the following:
array(3) {
[11]=>
array(1) {
[0]=>
int(10)
}
[13]=>
array(3) {
[0]=>
int(11)
[1]=>
int(12)
[2]=>
int(13)
}
[16]=>
array(3) {
[0]=>
int(14)
[1]=>
int(15)
[2]=>
int(16)
}
}
$result_array = array();
foreach($array_name as $sub_array){
$result_array[$sub_array['group']][] = $sub_array['id'];
}
This will loop through your input array and create a result two dimensional array indexed by your group values. To extract a group result just index for the group as such: $result_array['GROUP_NUMBER'];
Here is my take on this:
<?php
$arr = array(
array("id"=>10,"group"=>11),
array("id"=>11,"group"=>13),
array("id"=>12,"group"=>13),
array("id"=>13,"group"=>13),
array("id"=>14,"group"=>16),
array("id"=>15,"group"=>16),
array("id"=>16,"group"=>16)
);
echo "<pre>".print_r(groupsToArrays($arr),true)."</pre>";
function groupsToArrays($arr, $groupkey = "group") {
$main = array();
$group = 0;
$arr[] = array("id"=>"end", $groupkey => "0");
foreach($arr as $key => $value) {
if($group != $value[$groupkey]) {
if($key != 0) $main[$group] = $tempArray;
if($value['id'] == "end") continue;
$group = $value[$groupkey];
$tempArray = array();
}
$tempArray[] = $value;
}
return $main;
}
This function will loop through your array and check the $groupkey key and will add every match to it's own array.
This is the return:
Array
(
[11] => Array
(
[0] => Array
(
[id] => 10
[group] => 11
)
)
[13] => Array
(
[0] => Array
(
[id] => 11
[group] => 13
)
[1] => Array
(
[id] => 12
[group] => 13
)
[2] => Array
(
[id] => 13
[group] => 13
)
)
[16] => Array
(
[0] => Array
(
[id] => 14
[group] => 16
)
[1] => Array
(
[id] => 15
[group] => 16
)
[2] => Array
(
[id] => 16
[group] => 16
)
)
)
So now you can access that group array by doing:
$groups = groupsToArrays($arr);
print_r($groups[$groupID]);

Sorting multidimensional array by two user defined values

I need to sort a multidimensional array by two values.
For example in the array will be 4 keys.
Array(
Array
(
[0] => 4B642D022980E5EBAA7CF4B6E1CC93769921CB42
[1] => downloading
[2] => Title
[3] => 60
)
Array
(
[0] => 4B642D022980E5EBAA7CF4B6E1CC93769921CB42
[1] => downloading
[2] => Title
[3] => 30
)
Array
(
[0] => 4B642D022980E5EBAA7CF4B6E1CC93769921CB42
[1] => paused
[2] => Title
[3] => 30
)
Array
(
[0] => 4B642D022980E5EBAA7CF4B6E1CC93769921CB42
[1] => completed
[2] => Title
[3] => 100
)
)
Is there a way I can sort the array so that it would sort the arrays with key completed first, then downloading second, then paused third and then also sort the arrays containing downloading and paused from 100 down to 0 by the 3 key?
Desired output would be
Array(
Array
(
[0] => 4B642D022980E5EBAA7CF4B6E1CC93769921CB42
[1] => completed
[2] => Title
[3] => 100
)
Array
(
[0] => 4B642D022980E5EBAA7CF4B6E1CC93769921CB42
[1] => downloading
[2] => Title
[3] => 60
)
Array
(
[0] => 4B642D022980E5EBAA7CF4B6E1CC93769921CB42
[1] => downloading
[2] => Title
[3] => 30
)
Array
(
[0] => 4B642D022980E5EBAA7CF4B6E1CC93769921CB42
[1] => paused
[2] => Title
[3] => 30
)
)
uksort is what you need.
It is a sort that lets you define you own callback function.
This callback function is then used by uksort to reorder the array.
You need to write a function that will sort an array based on two criterias.
The first one is the alphabetical order of the field at indice 1 of your array (which contains the words completed, downloading, ...) and in case of tie you would then use the field at indice 3 of your array and sort in decreasing order.
Finally, you will need to pass the function you created as a parameter to uksort.
Hope it helps ! :)
You need to reformat your array and use array_multisort. It will also make thinks more readable:
<?php $ar = Array(
Array(
"id" => "4B642D022980E5EBAA7CF4B6E1CC93769921CB42",
"status" => "completed",
"title" => "Title",
"rank" => "100",
),
Array
(
"id" => "4B642D022980E5EBAA7CF4B6E1CC93769921CB42",
"status" => "downloading",
"title" => "Title",
"rank" => "60",
),
Array
(
"id" => "4B642D022980E5EBAA7CF4B6E1CC93769921CB42",
"status" => "downloading",
"title" => "Title",
"rank" => "30",
),
Array
(
"id" => "4B642D022980E5EBAA7CF4B6E1CC93769921CB42",
"status" => "paused",
"title" => "Title",
"rank" => "30",
),
);
var_dump($ar);
foreach ($ar as $key => $row) {
$status[$key] = $row['status'];
$rank[$key] = $row['rank'];
}
array_multisort($status, SORT_ASC, $rank, SORT_DESC, $ar);
var_dump($ar);
$array = [
[
'4B642D022980E5EBAA7CF4B6E1CC93769921CB42',
'downloading',
'Title',
'60',
],
[
'4B642D022980E5EBAA7CF4B6E1CC93769921CB42',
'downloading',
'Title',
'30',
],
[
'4B642D022980E5EBAA7CF4B6E1CC93769921CB42',
'paused',
'Title',
'30',
],
[
'4B642D022980E5EBAA7CF4B6E1CC93769921CB42',
'completed',
'Title',
'100',
]
];
usort($array, function($a, $b) {
if ($a[1] == $b[1]) {
if ($a[3] == $b[3]) {
return 0;
}
return ($a[3] > $b[3]) ? -1 : 1;
}
$status = ['completed', 'downloading', 'paused'];
foreach ($status as $st) {
if ($a[1] == $st)
return -1;
if ($b[1] == $st)
return 1;
}
return 0;
});
var_dump($array);

Multidimensional Array Find and Update The Value using PHP

I can't get suitable title for this thread (help me). I can't describe this problem so here the example of my problem.
My array :
Array ( [0] => Array ( [answer] => a [score] => 3 )
[1] => Array ([answer] => b [score] => 4 )
[2] => Array ( [answer] => h [score] => 3)
[3] => Array ( [answer] => a [score] => 4 ))
...
And I wanna get an output like this :
Array ( [0] => Array ( [answer] => a [score] => 7 )
[1] => Array ([answer] => b [score] => 4 )
[2] => Array ( [answer] => h [score] => 3))
...
You can see a change of score subkey in index key 0. This is happen because there is two value 'a' in answer subkey from index key 0 and 3. The score changed to 7 because of the sum of both (3+4). Really I don't have an idea for this, sorry for my english and thanks for help.
Feel free to comment. :)
$merged = array();
foreach ($array as $answer) {
if (isset($merged[$answer['answer']])) {
$merged[$answer['answer']]['score'] += $answer['score'];
} else {
$merged[$answer['answer']] = $answer;
}
}
var_dump($merged);
Check this answer, not using loop :
$arr = array ( array ( 'answer' => 'a', 'score' => 3 ),
array ( 'answer' => 'b', 'score' => 4 ),
array ( 'answer' => 'h', 'score' => 3),
array ( 'answer' => 'a', 'score' => 4 ));
$t = array_reduce($arr, function($result, $item) {
if(array_key_exists($item['answer'],$result)){
$result[$item['answer']] = array('answer' => $item['answer'], 'score' => $item['score']+$result[$item['answer']]['score']);
}
else{
$result[$item['answer']] = array('answer' => $item['answer'], 'score' => $item['score']);
}
return $result;
},array());
echo "<pre>";
print_r($t);
Output :
Array
(
[a] => Array
(
[answer] => a
[score] => 7
)
[b] => Array
(
[answer] => b
[score] => 4
)
[h] => Array
(
[answer] => h
[score] => 3
)
)
I though of using a temporary array:
/* Current array */
$array = array(
array("answer" => "a", "score" => 3),
array("answer" => "b", "score" => 4),
array("answer" => "h", "score" => 3),
array("answer" => "a", "score" => 4)
);
/* Using a temporary array */
$tmp_array = array();
foreach($array as $subarray){
if(array_key_exists($subarray["answer"], $tmp_array)){
$tmp_array[$subarray["answer"]] += $subarray["score"];
}else{
$tmp_array[$subarray["answer"]] = $subarray["score"];
}
}
/* Creating a new formatted array */
$new_array = array();
foreach($tmp_array as $key => $value){
$new_array[] = array("answer" => $key, "score" => $value);
}
print_r($new_array);

Categories