I have 2 arrays of different length:
$array1 = Array
(
[0] => Array
(
['_id'] => "Group1"
['M'] => 0
['F'] => 0
)
[1] => Array
(
['_id'] => "Group2"
['M'] => 0
['F'] => 0
)
[2] => Array
(
['_id'] => "Group3"
['M'] => 0
['F'] => 0
)
[3] => Array
(
['_id'] => "Group4"
['M'] => 0
['F'] => 0
)
)
$array2 = Array
(
[0] => Array
(
['_id'] => "Group2"
['M'] => 180
['F'] => 200
)
[1] => Array
(
['_id'] => "Group4"
['M'] => 360
['F'] => 500
)
)
I want to compare the values of ['_id'] in both array and if they match, I will replace the values of ['M'] and ['F'] in array1 with those from array2 based on the corresponding ['_id].
So my desired ouptput would be:
$array1 = Array
(
[0] => Array
(
['_id'] => "Group1"
['M'] => 0
['F'] => 0
)
[1] => Array
(
['_id'] => "Group2"
['M'] => 180
['F'] => 200
)
[2] => Array
(
['_id'] => "Group3"
['M'] => 360
['F'] => 500
)
[3] => Array
(
['_id'] => "Group4"
['M'] => 0
['F'] => 0
)
)
This is my code but I can't seem to get the values replaced with the new values. The values are still the same as before.
foreach ($array1 as $defArr)
{
foreach ($array2 as $dayArr)
{
if($dayArr['_id'] == $defArr['_id'])
{
$defArr['M'] = $dayArr['M'];
$defArr['F'] = $dayArr['F'];
}
}
}
This can be a one-character change:
foreach ($array1 as $defArr)
goes to
foreach ($array1 as &$defArr)
# ^
The & reference operator points to the original sub array in the foreach loop context rather than a temporary variable.
However, it's a bit safer to use the index explicitly:
foreach ($array1 as $i => $defArr) {
foreach ($array2 as $j => $dayArr) {
if ($dayArr['_id'] == $defArr['_id']) {
$array1[$i]['M'] = $array2[$j]['M'];
$array1[$i]['F'] = $array2[$j]['F'];
}
}
}
If speed is important or $array2 is large, the time complexity of your algorithm is O(n * m). I recommend hashing $array2 for fast lookups as follows (O(n)):
$lookup = array_reduce($array2, function ($a, $e) {
$a[$e['_id']] = $e;
return $a;
});
foreach ($array1 as $i => $e) {
if (array_key_exists($e['_id'], $lookup)) {
$array1[$i]['M'] = $lookup[$e['_id']]['M'];
$array1[$i]['F'] = $lookup[$e['_id']]['F'];
}
}
Try it!
<?php
$array1 = [['_id'=>'abc','M'=>0,'F'=>0],['_id'=>'abcd','M'=>0,'F'=>0],['_id'=>'abcde','M'=>0,'F'=>0]];
$array2 = [['_id'=>'abc','M'=>50,'F'=>300],['_id'=>'abcde','M'=>600,'F'=>700]];
foreach($array2 as $key=> $array2value){
$searched_in_array_1= array_search($array2value['_id'],array_column($array1,'_id'));
if(is_numeric($searched_in_array_1)) $array1[$searched_in_array_1] = $array2value;
}
var_dump($array1);
?>
You want to get a help with php array functions when dealing with arrays. I have used array_column and array_search functions for this
Related
I've been stuck on this for the better part of the day and I'm out of ideas. I have an array like this:
Array
(
[rank] => Array
(
[0] => 1
[1] => 2
[2] => 3
)
[name] => Array
(
[0] => 'Hideki'
[1] => 'Rory'
[2] => 'Sam'
[money] => Array
(
[0] => '$100'
[1] => '$200'
[2] => '$500'
)
)
and I have the task to create an array with the following format from it:
Array
(
[Hideki] => Array
(
[rank] => 1
[money] => '$100'
)
[Rory] => Array
(
[rank] => 2
[money] => '$200'
[Sam] => Array
(
[rank] => 3
[money] => '$500'
)
)
The catch is that 'rank' and 'money' have to be dynamic names
It should be simple as that:
$new = [];
foreach($array['name'] as $key => $name) {
$new[$name] = [
'rank' => $array['rank'][$key],
'money' => $array['money'][$key]
];
}
Little late but here my answear. My approach was to use the array_walk() function.
$array = [
'rank' => [1,2,3],
'name' => ['Hideki', 'Rory', 'Sam'],
'money' => ['$100', '$200', '$500'],
];
$i = 0;
$newArray = [];
array_walk($array['name'], function($name) use (&$i, $array, &$newArray) {
$newArray[$name] = ['rank'=> $array['rank'][$i], 'money' => $array['money'][$i]];
$i++;
});
print_r($newArray);
Run your first array through a foreach loop referencing only the "name" key and using key=>value pairs. Then reference the other keys from the first array when you build the new array, setting the value as the key to the second array.
You will need to first get the keys using array_keys() and use a nested foreach to loop through all the keys.
Example:
$keys1 = array_keys($array1);
foreach ($array1['name'] as $key => $value) {
$val2 = array();
foreach ($keys1 as $k){
if ($k != 'name') $val2[$k] = $array1[$k][$key];
}
$array2[$value] = $val2;
}
How to concatenate two arrays to a single array? In date position 0 and 1 are both concatenated in loop, my array code below here.
Array
(
[Apr-2019] => Array
(
[0] => Array
(
[DateUser] => Apr-2019
[withdarw_amount] => 4.00
)
[1] => Array
(
[current_deposit_amount] => 1.00
[current_deposit_table_refer] => 0.00
[current_deposit_user_refer] => 0.10
[DateUser] => Apr-2019
)
)
)
like my output:
[Apr-2019] => Array
(
[DateUser] => Apr-2019
[withdarw_amount] => 4.00
[current_deposit_amount] => 1.00
[current_deposit_table_refer] => 0.00
[current_deposit_user_refer] => 0.10
[DateUser] => Apr-2019
)
I have tried to use this code,
$data = array_merge($withdrow_amount,$data_casback,$cashbonus_data,$data_discount,$CurrentDeposit);
$months = array();
foreach($data as $date) {
$month = substr($date['DateUser'], 0, 8);
$months[$month][] = $date;
}
echo '<pre>'; print_r($months); die;
You can iterate over your array, using array_merge with the splat operator ... to flatten the internal arrays. Note you can't have two DateUser keys in an array so one will be deleted; assuming they have the same values as in your data that will not be a problem:
$array = array (
'Apr-2019' =>
array (
0 =>
array (
'DateUser' => 'Apr-2019',
'withdarw_amount' => 4.00
),
1 =>
array (
'current_deposit_amount' => 1.00,
'current_deposit_table_refer' => 0.00,
'current_deposit_user_refer' => 0.10,
'DateUser' => 'Apr-2019'
),
),
'Jun-2019' =>
array (
0 =>
array (
'DateUser' => 'Jun-2019',
'withdarw_amount' => 334.00
),
)
);
foreach ($array as &$arr) {
$arr = array_merge(...$arr);
}
print_r($array);
Output:
Array
(
[Apr-2019] => Array
(
[DateUser] => Apr-2019
[withdarw_amount] => 4
[current_deposit_amount] => 1
[current_deposit_table_refer] => 0
[current_deposit_user_refer] => 0.1
)
[Jun-2019] => Array
(
[DateUser] => Jun-2019
[withdarw_amount] => 334
)
)
Demo on 3v4l.org
You can use simple loops also to do that -
$new = [];
foreach ($array as $key =>$a) {
$new[$key] = []; // Define with key
foreach ($a as $v) {
$new[$key] += $v; // Concat
}
}
I've this type of array in PHP:
Array(
[100] => Array(
[1] => Array (
[AVA_Date] => 2019-04-18
[ROO_Id] => 100
[RAT_Id] => 9
)
[2] => Array (
[AVA_Date] => 2019-04-20
[ROO_Id] => 100
[RAT_Id] => 10
)
[4] => Array (
[AVA_Date] => 2019-04-21
[ROO_Id] => 100
[RAT_Id] => 10
)
[7] => Array (
[AVA_Date] => 2019-04-22
[ROO_Id] => 100
[RAT_Id] => 9
)
)
)
I would like to merge items on ROO_Id and RAT_Id.
Then, for the AVA_Date, I need to list them under a new array in the current array.
So, the desired output is:
Array(
[100] => Array(
[0] => Array (
[AVA_Date] => Array (
[0] => 2019-04-18
[1] => 2019-04-22
)
[ROO_Id] => 100
[RAT_Id] => 9
)
[1] => Array (
[AVA_Date] => Array (
[0] => 2019-04-20
[1] => 2019-04-21
)
[ROO_Id] => 100
[RAT_Id] => 10
)
)
)
Here what I have tried:
$newArrOtherRooms = array_reduce($newArr, function($acc, $val) {
$room = array_search($val['ROO_Id'], array_column($acc, 'ROO_Id'));
$rate = array_search($val['RAT_Id'], array_column($acc, 'RAT_Id'));
if($rate == $room && $room > -1) {
array_push($acc[$room]['AVA_Date'], $val['AVA_Date']);
}
else {
$new_arr = $val;
$new_arr['AVA_Date'] = [$val['AVA_Date']];
array_push($acc, $new_arr);
}
return $acc;
},[]);
But it doesn't work like I want.
There are a couple of issues with your code. Firstly, you need to wrap the array_reduce with a foreach over the outer level of $newArr. Secondly, your call to array_search doesn't consider the fact that a ROO_Id or RAT_Id value might exist more than once in the array, as it only returns the first key at which it finds the value. To work around this, you can use array_keys to get an array of key values for each ROO_Id and RAT_Id value, and then take the intersection of those two arrays using array_intersect to see if both are present in the same element. If so, you update that element, otherwise you create a new one:
foreach ($newArr as $key => $array) {
$newArrOtherRooms[$key] = array_reduce($array, function($acc, $val) {
$room = array_keys(array_column($acc, 'ROO_Id'), $val['ROO_Id']);
$rate = array_keys(array_column($acc, 'RAT_Id'), $val['RAT_Id']);
$common = array_intersect($room, $rate);
if(!empty($common)) {
array_push($acc[current($common)]['AVA_Date'], $val['AVA_Date']);
}
else {
$new_arr = $val;
$new_arr['AVA_Date'] = [$val['AVA_Date']];
array_push($acc, $new_arr);
}
return $acc;
},[]);
}
print_r($newArrOtherRooms);
Output:
Array(
[100] => Array(
[0] => Array (
[AVA_Date] => Array (
[0] => 2019-04-18
[1] => 2019-04-22
)
[ROO_Id] => 100
[RAT_Id] => 9
)
[1] => Array (
[AVA_Date] => Array (
[0] => 2019-04-20
[1] => 2019-04-21
)
[ROO_Id] => 100
[RAT_Id] => 10
)
)
)
Demo on 3v4l.org
There is absolutely no reason to be making all of those iterated function calls.
Use a nested loop to iterate the subset of data for each room, group on the room "rate id", and push all "available date" values into a subarray in the respective group. When the subset of data is fully iterated, push its grouped data into the result array.
Code: (Demo)
$result = [];
foreach ($newArr as $rooId => $rows) {
$groups = [];
foreach ($rows as $row) {
if (!isset($groups[$row['RAT_Id']])) {
$row['AVA_Date'] = (array) $row['AVA_Date'];
$groups[$row['RAT_Id']] = $row;
} else {
$groups[$row['RAT_Id']]['AVA_Date'][] = $row['AVA_Date'];
}
}
$result[$rooId] = array_values($groups);
}
var_export($result);
Output:
array (
100 =>
array (
0 =>
array (
'AVA_Date' =>
array (
0 => '2019-04-18',
1 => '2019-04-22',
),
'ROO_Id' => 100,
'RAT_Id' => 9,
),
1 =>
array (
'AVA_Date' =>
array (
0 => '2019-04-20',
1 => '2019-04-21',
),
'ROO_Id' => 100,
'RAT_Id' => 10,
),
),
)
I have an array like below: all the values I am getting one array only, but I don't want this way. This is the best way to do so, in php or jQuery both languages are ok for me
Array
(
[0] => Array
(
[val] => facebook
)
[1] => Array
(
[val] => snapchat
)
[2] => Array
(
[val] => instagram
)
[3] => Array
(
[expenses] => 986532
)
[4] => Array
(
[expenses] => 45456
)
[5] => Array
(
[expenses] => 56230
)
[6] => Array
(
[social_id] => 15
)
[7] => Array
(
[social_id] => 16
)
[8] => Array
(
[social_id] => 17
)
)
and I want to output like this..
$result = array(
array(
"val" => "Facebook",
"expenses" => "84512",
"social_id" => 1
),
array(
"val" => "Instagram",
"expenses" => "123",
"social_id" => 2
)
);
but this should be dynamic, the length of the above array can be varies
You can merge the arrays to one and use array_column to get all vals or expenses in a separate array.
Then foreach one array and build the new array with the key.
//$a = your array
// Grab each column separate
$val = array_column($a, "val");
$expenses= array_column($a, "expenses");
$social_id = array_column($a, "social_id");
Foreach($val as $key => $v){
$arr[] = [$v, $expenses[$key], $social_id[$key]];
}
Var_dump($arr);
https://3v4l.org/nVtDf
Edit updated with the 'latest' version of the array. My code works just fine with this array to without any changes.
to get that array style you can do it by hand for each array
function test(array ...$arr)
{
$result = array();
foreach ($arr as $key => $pair) {
foreach ($pair as $item => $value) {
$result[$item] = $value;
}
}
return $result;
}
$arr1 = test( ['facebook' => 1], ['expenses' => 100]);
print_r($arr1);
/* Array (
[facebook] => 1,
[expenses] => 100
)
*/
$arr2 = test( $arr1, ['more info' => 'info'] );
print_r($arr2);
/* Array (
[facebook] => 1,
[expenses] => 100,
[more info] => info
)
*/
you can pass it any number of
['Key' => 'Pair']
array('Key' => 'Pair')
or even a previous made array and it will add them up into 1 big array and return it
I have three arrays:
$arr1 = Array (
[0] => 1001
[1] => 1007
[2] => 1006);
$arr2 = Array (
[0] => frank
[1] => youi
[2] => nashua);
$arr3 = Array (
[0] => getfrankemail
[1] => getyouiemail
[2] => getnashuaemail);
Is there a way to combine these arrays to get a multidimensional array like this:?
Array (
[0] => Array (
[0] => 1001
[1] => frank
[2] => getfrankemail)
[1] => Array (
[0] => 1007
[1] => youi
[2] => getyouiemail)
[2] => Array (
[0] => 1006
[1] => nashua
[2] => getnashuaemail)
);
edit: what you are really looking for is a php version of the zip method in ruby/python.
For your specific example array_map works nicely:
$result = array_map(null, $arr1, $arr2, $arr3);
Output:
array (
0 =>
array (
0 => 1001,
1 => 'frank',
2 => 'frankemail',
),
1 =>
array (
0 => 1007,
1 => 'youi',
2 => 'youiemail',
),
2 =>
array (
0 => 1006,
1 => 'nashua',
2 => 'nashuaemail',
),
)
Iterate on the first array (looks like those are ids), and you can match the key for each value to indexes in $arr2 and $arr3
$result = array();
foreach ($arr1 as $key => $value) {
$result[] = array($value, $arr2[$key], $arr3[$key]);
}
as #kingkero mentions in his answer, you will get errors if they keys do not exist, which you could check for and ignore any rows where that is the case.
$result = array();
foreach ($arr1 as $key => $value) {
if (!isset($arr2[$key]) || !isset($arr3[$key])) {
continue;
}
$result[] = array($value, $arr2[$key], $arr3[$key]);
}
You could use array_push($aContainer, $arr1); or $aContainer[] = $arr[1]
You can do this with a loop in which you access each of the three arrays with the same key.
$result = array();
$max = count($arr1);
for ($i=0; $i<$max; $i++) {
$result[] = array(
$arr1[$i],
$arr2[$i],
$arr3[$i],
);
}
This could fire an out of bounds exception, since it doesn't check whether or not $arrX[$i] exists. Can you be sure that it does?