How to create dynamic array using existing array - php

I have on array of data in below.
Array
(
[0] => Array
(
[0] => Array
(
[rating] => 4
[review] => nice
)
[1] => Array
(
[rating] => 2
[review] => good
)
)
)
We customize above array and need to my custom array .
Need out put like below array. array always need 5 to 1 key because i am using this array for rating & review functionality.
Array
(
[0] => Array
(
[5] => Array
(
[rating] => 0
[review] => ""
)
[4] => Array
(
[rating] => 4
[review] => nice
)
[3] => Array
(
[rating] => 0
[review] => ""
)
[2] => Array
(
[rating] => 2
[review] => "good"
)
[1] => Array
(
[rating] => 0
[review] => ""
)
)
)

I managed to self-solve. Please find below solution as per output.
$arr1 = array(array("rating"=>4,"review"=>"nice"),array("rating"=>2,"review"=>"good"));
$final =a rray();
for ($i=5; $i>=1; $i--) {
foreach ($arr1 as $key =>$val) {
if ($val['rating']==$i) {
$final[$i] = array("rating"=>$val['rating'],"review"=>$val['review']);
break;
} else {
$final[$i] = array("rating"=>0,"review"=>"");
}
}
}
print_r($final);

Iterate each top level array (if you don't have multiple top level arrays, then you should consider restructuring your array structure to be more concise)
call array_column() on the level2 array so that the rating values are assigned as keys for their respective subarray.
Iterate in descending order from 5 to 1 while conditionally saving data to the output array.
Code: (Demo)
$input = [
[
['rating' => 4, 'review' => 'nice'],
['rating' => 2, 'review' => 'good']
]
];
foreach ($input as $x => $level2) {
$keyed = array_column($level2, null, 'rating'); // setup more efficient lookup
for($i = 5 ; $i > 0 ; --$i) {
$result[$x][$i] = isset($keyed[$i]) ? $keyed[$i] : ['rating' => 0, 'review' => ''];
}
}
var_export($result);
// output is as desired

Related

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

Sort array by key value and then get 5 highest and lowest values in array

I have an array called "playersArray" that looks like this:
Array (
[0] => Array ( [name] => Joe [holders] => 0 )
[1] => Array ( [name] => Bob [holders] => 100 )
[2] => Array ( [name] => Jake [holders] => 100 )
[3] => Array ( [name] => Mike [holders] => 100 )
[4] => Array ( [name] => Tim [holders] => -0.0145 )
[5] => Array ( [name] => Frank[holders] => 100 )
[6] => Array ( [name] => Scott [holders] => 0.0583 )
[7] => Array ( [name] => Doug[holders] => 0.1308 )
[8] => Array ( [name] => Tommy [holders] => 0.2516 )
[9] => Array ( [name] => Eric [holders] => 100 )
)
I have a function to sort this array by the "holders" value:
function compareHolders($a, $b) {
$aPoints < $a['holders'];
$bPoints < $b['holders'];
return strcmp($aPoints, $bPoints);
}
I loop through another array to create this array:
foreach ($players as $player) {
$player['name'] = $athlete['name'];
$player['holders'] = $total_result_yesterday;
$playersArray[] = $player;
}
I am trying to sort the array by "holder" value:
usort($playersArray, 'compareHolders');
print_r($playersArray);
Finally, I am trying to get the 5 highest and 5 lowest "holder" values in the newly sorted array:
$first_5_players = array_slice($playersArray, 0, 5, true);
$last_5_players = array_slice($playersArray, -5);
However, the sorting is not working correctly. The values due not show in sequential order as desired. How can I get the sorting to work correctly? Thank you!
your sorting function compareHolders is not correct. $aPoints and $bPoints are not defined. Since values for holders key are numeric you can use the comparision operators. Try doing following:
function compareHolders($a, $b) {
if ($a['holders'] == $b['holders']) {
// return 0 if equal
return 0;
}
return ($a['holders'] > $b['holders']) ? -1 : 1;
}
You are not actually comparing the two values in compareHolders(), because you're not declaring $aPpoints and $bPoints.
This should work:
function compareHolders($a, $b) {
$aPoints = $a['holders'];
$bPoints = $b['holders'];
return strcmp($aPoints, $bPoints);
}
or alternatively you could just return:
return strcmp($a['holders'], $b['holders']);
And then you could get rid of the strcmp(), since you're not comparing strings.

PHP - accesing to data of multi-dimensional array

I am trying to access data in a multi-dimenstional array.
I need to get values of this data (EC000001, EG000017, EN, EF007220) but I am struggling with foreach loops in PHP, especially when need to nested foreach Could you please help me and give me solution to access wanted data?
I need to loop over all $c's and then loop inside to get all needed data.This is how I collected value EC000001 before, but I believe that there is a better solution.
foreach ($c as $classCodes => $value) {
$classCode = key($c[$classCodes]); //classCode -> EC000001
}
Structure of array:
Array
(
**[EC000001]** => Array
(
[0] => **EG000017**
[1] => Array
(
[0] => Array
(
[0] => **EN**
[1] => Busbar terminal
)
[1] => Array
(
[0] => **nl-NL**
[1] => Aansluitklem stroomrail
)
)
[2] => Array
(
[0] => Array
(
[0] => **EF007220**
[1] => EU570448
[2] => Array
(
)
)
[1] => Array
(
[0] => EF007219
[1] => EU570448
[2] => Array
(
)
)
[2] => Array
(
[0] => EF000073
[1] =>
[2] => Array
(
[0] => EV009241
[1] => EV009472
)
)
[3] => Array
(
[0] => EF007092
[1] => EU570448
)
[4] => Array
(
[0] => EF004969
[1] => EU570126
)
)
)
)
I can not test it, but you can try with this inside the loop:
$value[0]; // -> 1
$value[1][0][0]; // -> 2
$value[1][1][1]; // -> 3
$EG000002Array[0][EG000001][0]
$EG000002Array[0][EG000001][1][0]
$EG000002Array[0][EG000001][1][1][1]
there are many ways to get array values from multi dimensional array
for example using foreach():
$flavors = array('Japanese' => array('hot' => 'wasabi',
'salty' => 'soy sauce'),
'Chinese' => array('hot' => 'mustard',
'pepper-salty' => 'prickly ash'));
// $culture is the key and $culture_flavors is the value (an array)
foreach ($flavors as $culture => $culture_flavors) {
// $flavor is the key and $example is the value
foreach ($culture_flavors as $flavor => $example) {
print "A $culture $flavor flavor is $example.\n";
}
}
or using for( ) :
$specials = array( array('Chestnut Bun', 'Walnut Bun', 'Peanut Bun'),
array('Chestnut Salad','Walnut Salad', 'Peanut Salad') );
// $num_specials is 2: the number of elements in the first dimension of $specials
for ($i = 0, $num_specials = count($specials); $i < $num_specials; $i++) {
// $num_sub is 3: the number of elements in each sub-array
for ($m = 0, $num_sub = count($specials[$i]); $m < $num_sub; $m++) {
print "Element [$i][$m] is " . $specials[$i][$m] . "\n";
}
}
the output should be like :
Element [0][0] is Chestnut Bun
Element [0][1] is Walnut Bun
Element [0][2] is Peanut Bun
Element [1][0] is Chestnut Salad
Element [1][1] is Walnut Salad
Element [1][2] is Peanut Salad
You can use recursion and regex to check if it's bolded :)
Notice we put& to $classCodes to pass it by reference and not
by value.
Function:
function get_bolded_data($c, &$classCodes = array()){
foreach($c as $k1 => $v1){
if(is_array($v1)){
//If $v1 is an array we call get_bolded_data() again and pass
//$v1 and $classCode
get_bolded_data($v1,$classCodes);
}else if(preg_match("/(\*\*).*(\*\*)/", $v1)){
$classCodes[] = $v1;
}
}
}
Usage:
$classCodes = array();
$c = array(
0 => array(
'**EC000001**' => array(
0 => '**EG000017**',
1 => array(
0 => array(
0 => '**EN**',
1 => 'Busbar terminal'
) ,
1 => array(
0 => '**nl-NL**',
1 => 'Aansluitklem stroomrail'
)
) ,
2 => array(
0 => array(
0 => '**EF007220**',
1 => 'EU570448',
2 => array()
) ,
1 => array(
0 => 'EF007219',
1 => 'EU570448',
2 => array()
) ,
2 => array(
0 => 'EF000073',
1 => '',
2 => array(
0 => 'EV009241',
1 => 'EV009472'
)
) ,
3 => array(
0 => 'EF007092',
1 => 'EU570448'
) ,
4 => array(
0 => 'EF004969',
1 => 'EU570126'
)
)
)
)
);
//Call our function
get_bolded_data($c, $classCodes);
Here is the result from var_dump:
array(4) {
[0]=>
string(12) "**EG000017**"
[1]=>
string(6) "**EN**"
[2]=>
string(9) "**nl-NL**"
[3]=>
string(12) "**EF007220**"
}

Intersection of two arrays using common key value for comparison

I want to perform an intersection of two arrays that have different structures, but both have one key common (fid). I want a new (filtered second) array after intersection with first array. below is my code and two arrays :
first array:
Array
(
[0] => Array
(
[fid] => 1
)
[1] => Array
(
[fid] => 3
)
)
Second array:
Array
(
[0] => Array
(
[fid] => 9
[functionality] => testing
[funcat_id] => 1
[name] => functionality
)
[1] => Array
(
[fid] => 1
[functionality] => add functionality
[funcat_id] => 1
[name] => functionality
)
[2] => Array
(
[fid] => 2
[functionality] => view functionality category
[funcat_id] => 1
[name] => functionality
)
[3] => Array
(
[fid] => 3
[functionality] => view functionality
[funcat_id] => 1
[name] => functionality
)
[4] => Array
(
[fid] => 4
[functionality] => edit functionality
[funcat_id] => 1
[name] => functionality
)
)
I want this Output :
Array
(
[0] => Array
(
[fid] => 1
[functionality] => add functionality
[funcat_id] => 1
[name] => functionality
)
[1] => Array
(
[fid] => 3
[functionality] => view functionality
[funcat_id] => 1
[name] => functionality
)
)
I tried this code but I'm not getting the right answer:
$result=array_intersect($array1,$array2);
//Or this also
$result=recursive_array_intersect_key($array1,$array2);
Please let me know, if any one can do this ?
I do not know if a function does exists to do this outright, but alternatively, you can just loop them instead:
$result = array();
foreach($array2 as $val2) {
foreach ($array1 as $val1) {
if($val2['fid'] == $val1['fid']) {
$result[] = $val2;
}
}
}
echo '<pre>';
print_r($result);
Sample Output
Or if you're using PHP 5.5 or greater:
$val1 = array_column($array1, 'fid');
$result = array_filter($array2, function($val2) use($val1) {
return in_array($val2['fid'], $val1);
});
foreach($array2 as $val)
{
$i=0;
foreach($array1 as $val1)
{
if($val['fid']==$val1['fid'])
{
$i++;
}
}
if($i!=0)
{
$a[]=$val;
}
}
print_r($a);

2d array - group by value and sum up same keys' values

Hello and thanks for taking the time to look at my question.
My current problem is that, I have the following array ($topics_percentage):
Array
(
[0] => Array
(
[id] => 8989
[cat] => Category 1
[completed] => 0
)
[1] => Array
(
[id] => 8919
[cat] => Category 2
[completed] => 1
)
[2] => Array
(
[id] => 8913
[cat] => Category 2
[completed] => 1
)
[3] => Array
(
[id] => 8947
[cat] => Category 1
[completed] => 1
)
[4] => Array
(
[id] => 8949
[cat] => Category 3
[completed] => 1
)
)
What I need to get, is something like the following example:
Array
(
[Category 1] => Array
(
[noncompleted] => 1
[completed] => 1
)
[Category 2] => Array
(
[completed] => 2
)
[Category 3] => Array
(
[completed] => 1
)
)
What I've tried so far is this:
$class_array = [];
foreach ($topics_percentage as $v) {
$complete = $v['completed'];
$class_array[$v['cat']][] =
($complete == 0 ? 'noncompleted' : 'completed');
}
Which returns the following:
Array
(
[Category 1] => Array
(
[0] => noncompleted
[1] => completed
)
[Category 2] => Array
(
[0] => completed
[1] => completed
)
[Category 3] => Array
(
[0] => completed
)
)
I'm weak when it comes to arrays, and can't figure out the logic.
Thanks in advance.
Try this:
$values = array_unique(array_map(
function ($v) { return $v['cat']; },
$array
));
$result = array();
foreach ($values as $val) {
$flt = array_filter($array, function ($v) use ($val) {
return $v['cat'] == $val;
});
$cnt = count(array_filter($array, function ($v) use ($val) {
return $v['completed'];
}));
$result[$val] = array(
'completed' => $cnt,
'noncompleted' => count($flt) - $cnt
);
}
Try this:
foreach ($topics_percentage as $v) {
$complete = $v['completed'];
if ($complete == 1) {
$class_array[$v['cat']]['completed']++;
} else {
$class_array[$v['cat']]['uncompleted']++;
}
}
You should, of course, preinitialize the array before you count up values, but the basic idea is to use array cells as numeric values to be added or substracted from.

Categories