Get highest value from associative array foreach - php

I'm implementing the first answer shown here: Finding Highest Value in Associative Array
but what's happening is it assigns the first value it finds as the "max", then when it finds the next highest value, it ALSO assigns "max" to that value.
of course my goal is to only assign "max" to the highest value.
the issue must be the way I present the values.
Here is the array (i'm assigning "max" to the 'sum' index on a PER WEEK basis):
Array
(
[0] => stdClass Object
(
[userid] => 1
[week] => 1
[sum] => 28
[user] => al
)
[1] => stdClass Object
(
[userid] => 1
[week] => 2
[sum] => 33
[user] => al
)
[2] => stdClass Object
(
[userid] => 1
[week] => 3
[sum] => 29
[user] => al
)
...
[17] => stdClass Object
(
[userid] => 26
[week] => 1
[sum] => 14
[user] => bob
)
[18] => stdClass Object
(
[userid] => 26
[week] => 2
[sum] => 23
[user] => bob
)
[19] => stdClass Object
(
[userid] => 26
[week] => 3
[sum] => 35
[user] => bob
)
...
[34] => stdClass Object
(
[userid] => 27
[week] => 1
[sum] => 36
[user] => chuck
)
[35] => stdClass Object
(
[userid] => 27
[week] => 2
[sum] => 23
[user] => chuck
)
[36] => stdClass Object
(
[userid] => 27
[week] => 3
[sum] => 29
[user] => chuck
)
But I'm delivering the data through a couple of foreach loops:
<?php
$resultsByUser = array();
$temp = array();
foreach($results as $result) {
$resultsByUser[$result->user][$result->week] = $result->sum;
}
foreach($resultsByUser as $user => $resultsByWeek) {
print "<tr><td>$user</td>";
ksort($resultsByWeek);
foreach($resultsByWeek as $week => $sum) {
$temp[$week] = max(
isset($temp[$week]) ? $temp[$week] : $sum,
$sum);
if($week == $week) {
if($temp[$week] == $sum) { ?>
<td><?php echo $sum; ?><span><i class='fa fa-trophy'></i></span></td>
<?php } else { ?>
<td><?php echo $sum; ?></td>
<?php }
}
}
} ?>
How can I force the $temp[week] aka "max" function to loop through the whole associative array of weekly values before assigning the trophy icon?
EDIT:
After the comments, I've modified the final couple of stanzas to the below, but now I don't get the trophy assigned to any value. What am I missing?
foreach($resultsByWeek as $week => $sum) {
$temp[$week] = max(
isset($temp[$week]) ? $temp[$week] : $sum,
$sum); ?>
<td><?php echo $sum; }}?>
<?php if($sum == $temp[$week]) { ?> <span><i class='fa fa-trophy'></i></span></td>
<?php } ?>

In the answer you received on the other post:
$temp = array();
foreach ($data as $item) {
foreach ($item as $key => $value) {
$temp[$key] = max(
isset($temp[$key]) ? $temp[$key] : $value,
$value);
}
}
You go through all the array of objects, updating the max value as you go through all the data elements.
That means that you will only have the maximum value (with 100% certainty) when you reach the end of that loop.
If what you want is to print a trophy icon alongside the maximum value, you need to know beforehand what is that element.
You have 2 ways to do that:
1. Use two loops
Use a first loop, without writes, just to find the maximum values.
Then use a second loop, with writes, writing the object data. And, if the maximum value gathered in the first loop equals the object data, draw the trophy icon.
Something like:
$temp = array();
foreach ($data as $item) {
foreach ($item as $key => $value) {
$temp[$key] = max(
isset($temp[$key]) ? $temp[$key] : $value,
$value);
}
}
foreach ($data as $item) {
foreach ($item as $key => $value) {
echo $user_data;
if ($user_data_sum == $temp[$key])
echo "<trophy image>";
}
}
2. Save on the object that it is the maximum value (or the trophy)
If you can edit the objects, save the maximum value on the object. That will reduce the processing time, since you'll only need a single loop instead of two as above.
Something like:
[0] => stdClass Object
(
[userid] => 1
[week] => 1
[sum] => 28
[user] => al
[is_max] => false
)
[1] => stdClass Object
(
[userid] => 1
[week] => 2
[sum] => 33
[user] => al
[is_max] => true
)
Using on the loop:
foreach ($data as $item) {
foreach ($item as $key => $value) {
echo $user_data;
if ($user_data_is_max)
echo "<trophy image>";
}
}
Or even:
[0] => stdClass Object
(
[userid] => 1
[week] => 1
[sum] => 28
[user] => al
[trophy] => ""
)
[1] => stdClass Object
(
[userid] => 1
[week] => 2
[sum] => 33
[user] => al
[trophy] => "<trophy image>"
)
Using on the loop just prints (without needing the if):
foreach ($data as $item) {
foreach ($item as $key => $value) {
echo $user_data . $user_data_trophy;
}
}

Related

How to iterate values in foreach and create array with new values in cakephp 3.x

I have below code from which i am getting Below data in response..
public function getCategory(){
$this->autoRender = False;
$list = TableRegistry::get('Subproducts');
$supplierId = $this->request->data['supplierId'];
if($this->request->is('ajax')) {
if(!empty($supplierId)) {
$query1 = $list->find()->contain(['Products'])
->where(['Subproducts.supplier_id =' => $supplierId]);
$data = $query1->hydrate(false)->toArray();
if(!empty($data)){
**Print_r($data);**
**foreach ($data as $value){
print_r($value);
}**
//echo json_encode(array("category"=>$newArray));
exit;
}
}
}
}
Below Data i am getting from above code
Array
(
[supplier_id] => 40
[product] => Array
(
[id] => 45
[name] => PLASTIC ITEM
[is_deleted] => 0
)
)
Array
(
[supplier_id] => 40
[product] => Array
(
[id] => 50
[name] => RAW MATERIAL
[is_deleted] => 0
)
)
I want to collect Id and Name of product array in $newArray, but i am not able to iterate product array and dont know how to add id and name of product in $newArray. Can anyone please help me to iterate product array value and create new array which contains only Id and Name.
I need help inside to iterate values and create new array with only id and name of product array.
**Print_r($data) is getting below data, I have added print_r($data); like below code, i mean before foreach loop..
if(!empty($data)){
print_r($data);
foreach ($data as $value) { }
}
Array
(
[0] => Array
(
[id] => 468
[supplier_id] => 40
[buy_price] => 6.23
[sell_price] => 7.87
[category_id] => 45
[product_name] => test1
[is_deleted] => 0
[created] => Cake\I18n\FrozenTime Object
(
[date] => 2021-10-12 09:48:20.000000
[timezone_type] => 3
[timezone] => UTC
)
)
[1] => Array
(
[id] => 469
[supplier_id] => 40
[buy_price] => 44.89
[sell_price] => 7.87
[category_id] => 50
[product_name] => test
[is_deleted] => 0
[created] => Cake\I18n\FrozenTime Object
(
[date] => 2021-10-12 11:44:28.000000
[timezone_type] => 3
[timezone] => UTC
)
)
)
Loop over the inner array and grab the parts you are interested in from there
UPDATE: Ok so it looks like the array is not inside another so a simple foreach will do it
$newArray = []; // initialise the array
foreach ($data as $inner) {
$newArray[] = [ 'id' => $inner['product']['id'],
'name' => $inner['product']['name']
]
}
$newArray = []; // initialise the array
foreach ($data as $key=> $value) {
$newArray[] = [
'id' => $value['product']['id'],
'name' => $value['product']['name']
];
}

PHP: Comparison of array value not working?

I am trying to comparing array value, if value found if(isset($row['height']) == ['3455']) then print the array value but it is not working it is return all the array which includes not matching value too.
How will I compare a value and if value found then print that single value of array not all value.
Here is my print_r value
Array
(
[0] => Array
(
[id] => 1
[name] => Bradeley Hall Pool
[postcode] => CW1 5QN
[lat] => 53.10213
[lon] => -2.41069
[size] => 1.60
[pegs] => 21
[distance] => 26.6
[suitability] => Array
(
[0] => Array
(
[species] => Barbel
[species] => 1
[record] => 1
[weight] => 2.721554
[length] => 40
[height] => ['abc','345m','3455']
)
)
)
[1] => Array
(
[id] => 2
[name] => Farm Pool
[postcode] => CW9 6JQ
[lat] => 53.320502
[lon] => -2.549049
[size] => 0.88
[pegs] => 8
[distance] => 15.4
[suitability] => Array
(
[0] => Array
(
[species] => Barbel
[species] => 1
[record] => 1
[weight] => 2.721554
[length] => 40
[height] => ['33','3455','3mnc']
)
)
)
)
My code -
foreach( $cursor as $row){
foreach ($row['suitability'] as $item) {
if(isset($item['height']) == ['3455']){
echo 'yes';
echo '<pre>';
print_r($item['height']);
} else{
echo 'no';
}
}
}
I think the most obvious issue may be that [height] => ['abc','345m','3455'] is not an array, otherwise the print_r() would have shown it as one. So it must be a string.
So this would work
foreach( $cursor as $row){
foreach ($row['suitability'] as $suit) {
// can we find the string in there somewhere
if (strpos($suit['height'], '3455') !== false) {
echo 'yes ';
echo $suit['height'];
echo PHP_EOL;
} else{
echo 'no';
}
}
}
There are shorter ways, but you should use isset to check for the existence of the array key. Once you know it is present, you can in_array to check for a specific value within the height array.
<?php
foreach($cursor as $row){
// Check if the row has the key `suitability`.
if (isset($row['suitability'])) {
foreach ($row['suitability'] as $item) {
// Check if the item has the key `height`.
if (isset($item['height'])) {
// Assuming `height` is always an array.
if (in_array('3455', $item['height']) {
// Yes.
}
}
}
}
}

Delete element from triply nested array PHP

I am struggling to figure out how to remove elements from a triple nested array based on a value at the deepest level. I would like to remove any position sub-array where time == "NA". My array structure is as follows.
Array
(
[0] => Array
(
[Id] => 151601
[First_Name] => JOHN
[Last_Name] => DOE
[Location_Id] => 10
[Positions] => Array
(
[North] => Array
(
[Current_Level] => 4
[Last_Date] => 11/7/2001
[Time] => 4:15 AM
)
[East] => Array
(
[Current_Level] => 4
[Last_Date] => 7/10/2003
[Time] => 7:30 PM
)
[South] => Array
(
[Current_Level] => 2
[Last_Date] => 8/10/2007
[Time] => NA
)
[West] => Array
(
[Current_Level] => NA
[Last_Date] => NA
[Time] => NA
)
)
)
So my end result would be
Array
(
[0] => Array
(
[Id] => 151601
[First_Name] => JOHN
[Last_Name] => DOE
[Location_Id] => 10
[Positions] => Array
(
[North] => Array
(
[Current_Level] => 4
[Last_Date] => 11/7/2001
[Time] => 4:15 AM
)
[East] => Array
(
[Current_Level] => 4
[Last_Date] => 7/10/2003
[Time] => 7:30 PM
)
)
)
This is what I am currently trying but it is throwing an illegal offset type error. I think I'm just not unsetting the right thing. I can get it to echo all the correct subarrays but when I try to unset I get an offset error.
foreach($records as $record) {
foreach ($record as $value) {
if (is_array($value)) {
foreach ($value as $position) {
if($position["Time"] == "NA") {
unset($records[$record][$value]);
}
}
}
}
}
With passing array element by reference and filtering function you can reduce your code to:
foreach($records as &$record) {
$record['Positions'] = array_filter(
$record['Positions'],
function ($v) {
return $v['Time'] !== 'NA';
}
);
}
Fiddle here.
Php uses a copy of the array in the foreach. You might also use a key in the foreach and use that to unset the value in the original $records array.
foreach ($records as $keyRecord => $record) {
foreach ($record as $key => $value) {
if (is_array($value)) {
foreach ($value as $keyPosition => $position) {
if ($position["Time"] == "NA") {
unset($records[$keyRecord][$key][$keyPosition]);
}
}
}
}
}
print_r($records);
Output
Array
(
[0] => Array
(
[Id] => 151601
[First_name] => John
[Positions] => Array
(
[North] => Array
(
[Current_Level] => 4
[Last_Date] => 11/7/2001
[Time] => 4:15 AM
)
[East] => Array
(
[Current_Level] => 4
[Last_Date] => 7/10/2003
[Time] => 7:30 PM
)
)
)
)
Php demo

Increment count for value in foreach loop PHP

I am trying to count the instances of rfid from one array to insert into another array so I can use this data to create charts.
At the moment my code is as follows
if ($message == "Broken" && $message_type == "BreakBeam" && $previous==$cat_id) {
$total = 1;
$splitTimeStamp = explode(" ",$eventtime);
$date = $splitTimeStamp[0];
$time = $splitTimeStamp[1];
$events[$c]['date'] = $date;
$events[$c]['device'] = $device;
$events[$c]['time']= $time;
$events[$c]['rfid']= $previous;
$events[$c]['count']=$total;
$c++;
}
}
$a = array();
$i=0;
foreach($events as $event){
if(isset($a[$event['rfid']])){
$a['rfid_id'][$event['rfid']]++;
}else{
$a['rfid_id'][$event['rfid']]=1;
}
if(isset($a[$event['date']])){
$a['dateinsert'][$event['date']]++;
}else{
$a['dateinsert'][$event['date']] =1;
}
}
$rfid = array();
// those are the ones we're going to put in!
foreach($a as $key => $count) {
foreach($count as $eventdetails['rfid_id'] => $event){
// so $key is the [rfid] key of the entry and $count is the count (all 1's?) in it
if (isset($rfid[$key])) {
$rfid[$key]+=$event;
}
else {
$rfid[$key]=$event;
}
}
}
Which outputs as follows :
Array
(
[0] => Array
(
[date] => 2020-09-17
[device] => 2
[time] => 15:51:37
[rfid] => 23641
[count] => 1
)
[1] => Array
(
[date] => 2020-09-17
[device] => 2
[time] => 15:52:20
[rfid] => 5609
[count] => 1
)
[2] => Array
(
[date] => 2020-09-17
[device] => 2
[time] => 15:53:23
[rfid] => 5609
[count] => 1
)
[3] => Array
(
[date] => 2020-09-17
[device] => 2
[time] => 16:02:44
[rfid] => 5609
[count] => 1
)
)
Array
(
[rfid_id] => Array
(
[23641] => 1
[5609] => 1
)
[dateinsert] => Array
(
[2020-09-17] => 1
)
)
Array
(
[rfid_id] => 2
[dateinsert] => 1
)
Ideally, I would like to achieve the following :
Array
(
[rfid_id] => Array
(
[23641] => 1
[5609] => 3
)
[dateinsert] => Array
(
[2020-09-17] => 1
)
)
or something to that effect, where I can look at the date, rfid codes and the time each was read on that date.
You simply missing the path in the assignment loop.
Same goes for rfid and date so I just explain on rfid.
You check the isset on one path but is not exist set on another - this cause the path to never exist - that why you keep getting 1's.
Look at:
foreach($events as $event){
if(isset($a[$event['rfid']])){
$a['rfid_id'][$event['rfid']]++;
} else {
$a['rfid_id'][$event['rfid']]=1;
}
}
Notice $a[$event['rfid']] is NOT the same as $a['rfid_id'][$event['rfid']].
You should change the if statement to be: if (isset($a['rfid_id'][$event['rfid']))

PHP Array handling for first children

I'm so tired of arrays today - thrown me all over the place.
So, here's the output of an array:
Array
(
[2010091907] => Array
(
[home] => Array
(
[score] => Array
(
[1] => 7
[2] => 17
[3] => 10
[4] => 7
[5] => 0
[T] => 41
)
[abbr] => ATL
[to] => 2
)
Array
(
[2010091909] => Array
(
[home] => Array
(
[score] => Array
(
[1] => 7
[2] => 17
[3] => 10
[4] => 7
[5] => 0
[T] => 41
)
[abbr] => ATL
[to] => 2
)
Array
(
[2010091901] => Array
(
[home] => Array
(
[score] => Array
(
[1] => 7
[2] => 17
[3] => 10
[4] => 7
[5] => 0
[T] => 41
)
[abbr] => ATL
[to] => 2
)
I'm going to be writting a preg_match to iterate each [2010091907], but before I can, I do not understand how to get this piece of information, or how to call it. I'd be doing something like:
$json=json_decode($data,true);
foreach ($json['dont-know-what-to-call-it'] as $key => $value) {
echo "Key: ".$key."; Value: ".$value."<br />";
}
I just don't know how to call each one of those [2010091901] blocks, like what name I'm suppose to call them as. I know how to call the stuff under score, since it's named "score", and the data is under all that. I don't know how to get the key/value of the initial "sections" of the array. In the end, I'm going to want to grab each [2010091901], manipulate/use the data that is inbetween each one of the [2010091901], and then go to the next "record".
$date_keys = array_keys($json) would give (0 => 2010091907, 1 => 2010091909, ...) . then you could do
foreach ($date_keys as $d) {
foreach ($json[$d] as $key => $value) {
...
Also, if you do not actually need the indices of the outer array (the date values - 2010091907, etc) than you could just do
foreach ($json as $j) {
foreach ($j as $key => $value) {
...
ignoring the keys of $json
Can't you just nest foreach()s?
foreach($jsondata as $somedate => $value){
//do you actually need $somedate?
foreach($value['home']['score'] as $score){
echo $score.PHP_EOL;
}
}
You can just do
$json = json_decode($data, true);
foreach($json as $ymd => $data)
{
// $ymd = [2010091907, 2010091909,… ]
// $data is the array starting with the key home. so $data['home']['score'][1] = 7 for the first iteration
}
This answer your question? It's not 100% clear what you're asking

Categories