Filtering two php arrays - php

I have two arrays. I have combined both the arrays to output the total
1st array =
$farray = Array (
[0] => Array (
[1] => Array (
[ED] => 15
[EN] => 14
)
)
[1] => Array (
[2] => Array (
[ED] => 5
[EN] => 10
)
)
)
2nd Array =
$tarray = Array (
[0] => Array (
[1] => Array (
[ED] => 45
[EN] => 50
)
)
[1] => Array (
[2] => Array (
[ED] => 38
[EN] => 40
)
)
)
The combination of the above two arrays:
$all = Array (
[0] => Array (
[1] => Array (
[ED] => 60
[EN] => 64
)
)
[1] => Array (
[2] => Array (
[ED] => 43
[EN] => 50
)
)
)
Now I want to use the first array and the second array for inserting condition into the following codes:
$fscore = array_reduce(
$farray,
function($farray, $item) {
$id = key($item);
$scores = $item[$id];
$farray[$id] = array(
"score" => array_sum($scores),
"farray"=> min($scores)>=7
);
return $farray;
},
array()
);
The above attempt works and output the following (print_r($fscore)):
Array (
[1] => Array (
[score] => 124
[farray] => 1
)
[2] => Array (
[score] => 93
[farray] => 0
)
)
But I want to put more conditions to it and combine with the $tarray like below:
$all= array_reduce(
$all,
function($all, $item) {
$id = key($item);
$scores = $item[$id];
$all[$id] = array(
"score" => array_sum($scores),
"farray"=> min($scores)>=7
//if tarray key==ED 23 else 26 for minimum `$scores`
"tarray"=> min($scores)>='ED'? 23:26//ternary operator
);
return $all;
},
array()
);
I don't know how to insert the $tarray. As stated earlier, without the $tarray, it works.
My attempts failed and does not output expected result. In this question I only used ED and EN (score keys) to save more space. The minmum score expected for $farray is greater than or equal to 7 whereas the minimum score expected for $tarray is 23/26. If the score key is ED in $tarray, the minimum score is greater than or equal to 23, else it must be 26. Depending on those conditions, I want to return true or false value. Please help. Below is my attempt:
$farray = array(
array (
1=> array(
"ED"=>15,
"EN"=>14
)
),
array(
2=>array(
"ED"=>5,
"EN"=>10
)
)
);
$tarray = array (
array (
1 => array (
"ED" => 45,
"EN" => 50
)
),
array (
2 => array (
"ED" => 38,
"EN" => 40
)
)
);
$combine = array (
array (
1 => array (
"ED" => 60,
"EN" => 64
)
),
array (
2 => array (
"ED" => 43 ,
"EN" => 50
)
)
);
function filtertArray($value){
foreach($value as $key =>$val){
foreach($val as $k=>$v){
foreach($v as $t=>$m){
if($t=='ED'){
return $m>=23;
}else{
return $m>=26;
}
}
}
}
}
function filterfArray($value){
foreach($value as $key =>$val){
foreach($val as $k=>$v){
foreach($v as $t=>$m){
return $m>=7;
}
}
}
}
$all = array_reduce(
$combine,
function($combine, $item) use ($farray, $tarray) {
$id = key($item);
$scores = $item[$id];
$combine[$id] = array(
"score" => array_sum($scores),
"farray"=> array_filter($farray,"filterfArray"),
"tarray"=> array_filter($tarray,"filtertArray")
);
return $combine;
},
array()
);
echo "<pre>";
print_r($all);
echo "</pre>";
This outputs:
E_WARNING : type 2 -- Invalid argument supplied for foreach()
The expected output from this code is:
Array (
[1] => Array (
[score] => 124
[farray] => true//1
[tarray] => true//1
)
[2] => Array (
[score] => 93
[farray] => false//0
[tarray] => true//1
)
)

I don't think I'd bother trying to spice this answer up with an array_reduce() call. It is more important to comprehensibly deliver the correct comparisons and result. You are certainly welcome to convert my series of foreach loops to array functions.
My latest edit added more sample score data with the newly advised keys. The adjustment to $fscore's tarray comparison is that now the lowest non-ED score is compared against 26.
Code: (Demo)
$farray=[[1=>['ED'=>15,'EN'=>14,'MT'=>16,'MZ'=>20]],[2=>['ED'=>5,'EN'=>10,'MT'=>36,'MZ'=>30]]];
$tarray=[[1=>['ED'=>45,'EN'=>50,'MT'=>28,'MZ'=>27]],[2=>['ED'=>38,'EN'=>40,'MT'=>56,'MZ'=>60]]];
// generate $all
foreach($farray as $i=>$a){
foreach($a as $n=>$scores){
foreach($scores as $k=>$v){
$all[$i][$n][$k]=$v+$tarray[$i][$n][$k]; // sum the relative scores
}
}
}
var_export($all);
echo "\n\n";
// generate $fscores
$sub23_keys=array_flip(['ED']); // store list of keys that have lower score minimum
foreach($all as $i=>$a){
foreach($a as $n=>$scores){
$fscores[$n]['score']=array_sum($scores);
$fscores[$n]['farray']=min($farray[$i][$n])>=7; // check that both ED and EN scores are >=7
$fscores[$n]['tarray']=min(array_intersect_key($tarray[$i][$n],$sub23_keys)) && min(array_diff_key($tarray[$i][$n],$sub23_keys))>=26;
}
}
var_export($fscores);
Output:
// $all=
array (
0 =>
array (
1 =>
array (
'ED' => 60,
'EN' => 64,
'MT' => 44,
'MZ' => 47,
),
),
1 =>
array (
2 =>
array (
'ED' => 43,
'EN' => 50,
'MT' => 92,
'MZ' => 90,
),
),
)
//$fscores=
array (
1 =>
array (
'score' => 215,
'farray' => true,
'tarray' => true,
),
2 =>
array (
'score' => 275,
'farray' => false,
'tarray' => true,
),
)

Related

How to concatenate two array in php

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
}
}

Group subsets of data in 3-level array by identifying column

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,
),
),
)

Array inside array or nested array

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

how to group a multidimensional array using a condition in php?

I have the following array
Array
(
[0] => Array
(
[shop] => 3
[price] => 332.00
)
[1] => Array
(
[shop] => 1
[price] => 3335.00
)
[2] => Array
(
[shop] => 3
[price] => 235.00
)
[3] => Array
(
[shop] => 1
[price] => 402.50
)
[4] => Array
(
[shop] => 3
[price] => 332.00
)
)
I need to group using shop and get get the minimum price of each shop in the array.
The expected result is as follows
Array
(
[0] => Array
(
[shop] => 3
[price] => 235.00
)
[1] => Array
(
[shop] => 1
[price] => 402.50
)
)
How will I do it?
You need to use additional variable
<?php
$arr = Array
(
0 => Array
(
'shop' => 3,
'price' => 332.00
),
1 => Array
(
'shop' => 3,
'price' => 232.00
),
2 => Array
(
'shop' => 1,
'price' => 232.00
),
3 => Array
(
'shop' => 3,
'price' => 432.00
),
4 => Array
(
'shop' => 1,
'price' => 132.00
),
);
$filtered = array();
foreach($arr as $prices){
if(FALSE === isset($filtered[$prices['shop']]) || $filtered[$prices['shop']]['price'] > $prices['price']){
$filtered[$prices['shop']] = $prices;
}
}
$filtered = array_values($filtered);
print_r($filtered);
This is very fast example how you can achieve this
It's rather simple.
Create a new array where you will host your stores as keys, and prices as values. What you want to do is to go through each element and first if the key does not exists in your new array, add it and its value. If however the key already exists, check if the current value is lower, and save it if true.
$grouped = [];
foreach ($arr as $k => $v) {
foreach ($k as $key => $value) {
if (isset($grouped[$key])) {
if ($value < $grouped[$key]) {
$grouped[$key] = $value;
}
} else {
$grouped[$key] = $value;
}
}
}
Your new array will look like this (store => price):
[
1 => 402.50,
3 => 235.00
]

Merging two arrays with weight of index in both

I have two array like this and want to merge like
Take 1st index Array 1 check
if it is present in Array 2
Insert in Array 3
add weight of Array 1 and Array 2
else if not present
take 1st index of Array 2
Take 1st index of Array 2 and check
if it is present in Array 1
Insert in Array 3
add weight of Array 1 and Array 2
else if not present
take 2nd index of Array 1
Take 2nd index of Array 1 and check
if it is present in Array 2
Insert in Array 3
add weight of Array 1 and Array 2
else if not present
take 1st index of Array 2
Take 1st index of Array 2 and check
Note above logic is for given example
For Example
Array 1
(
[144] => Array
(
[weight] => 2
)
[145] => Array
(
[weight] => 1
)
[177] => Array
(
[weight] => 1
)
)
Array 2
(
[93] => Array
(
[weight] => 4
)
[133] => Array
(
[weight] => 4
)
[144] => Array
(
[weight] => 4
)
[145] => Array
(
[weight] => 4
)
[141] => Array
(
[weight] => 1
)
)
I want result as
Array 3
(
[144] => Array
(
[weight] => 6
)
[145] => Array
(
[weight] => 5
)
[93] => Array
(
[weight] => 4
)
[133] => Array
(
[weight] => 4
)
[177] => Array
(
[weight] => 1
)
[141] => Array
(
[weight] => 1
)
)
Thanks in Advance
$out = array();
foreach ($arr1 as $key => $val) {
if (isset($out[$key]['weight'])) {
$out[$key]['weight'] += $val['weight'];
} else {
$out[$key]['weight'] = $val['weight'];
}
}
foreach ($arr2 as $key => $val) {
if (isset($out[$key]['weight'])) {
$out[$key]['weight'] += $val['weight'];
} else {
$out[$key]['weight'] = $val['weight'];
}
}
print_r($out);
Also, if you have an unknown number of arrays to work with you can do this:
$arrays = array (
$arr1,
$arr2,
$arr3
// ...
};
$out = array();
foreach ($arrays as $array) {
foreach ($array as $key => $val) {
if (isset($out[$key]['weight'])) {
$out[$key]['weight'] += $val['weight'];
} else {
$out[$key]['weight'] = $val['weight'];
}
}
}
print_r($out);
You seems to want second array first,
then append first array
maybe this is works
$a = ...; //first array
$b = ...; // second array
var_export($a);
var_export($b);
$rtn = $tmp = array();
foreach ($b as $idx=>$arr)
{
if (isset($a[$idx]))
{
$rtn[$idx]['weight'] = $arr['weight'] + $a[$idx]['weight'];
unset($a[$idx]);
}
else
{
$tmp[$idx]['weight'] = $arr['weight'];
}
}
$res = $rtn+$tmp+$a;
print_r($res);
result
array (
144 =>
array (
'weight' => 2,
),
145 =>
array (
'weight' => 1,
),
177 =>
array (
'weight' => 1,
),
)array (
93 =>
array (
'weight' => 4,
),
133 =>
array (
'weight' => 4,
),
144 =>
array (
'weight' => 4,
),
145 =>
array (
'weight' => 4,
),
141 =>
array (
'weight' => 1,
),
)Array
(
[144] => Array
(
[weight] => 6
)
[145] => Array
(
[weight] => 5
)
[93] => Array
(
[weight] => 4
)
[133] => Array
(
[weight] => 4
)
[141] => Array
(
[weight] => 1
)
[177] => Array
(
[weight] => 1
)
)
it's very simple task:
array_walk($a, function(&$value, $key, $b){
$value["weight"] += isset($b[$key]["weight"])?$b[$key]["weight"]:0;
}, $b);
$ret = $a+$b
given input:
$a = array(
1 => array(
"weight" => 1
),
2 => array(
"weight" => 5
)
);
$b = array(
1 => array(
"weight" => 2
),
3 => array(
"weight" => 4
)
);
would produce:
array(3) {
[1]=>
array(1) {
["weight"]=>
int(3)
}
[2]=>
array(1) {
["weight"]=>
int(5)
}
[3]=>
array(1) {
["weight"]=>
int(4)
}
}

Categories