This question already has answers here:
Find highest value in multidimensional array [duplicate]
(9 answers)
Closed 5 years ago.
i need to get the the max or highest value in a multi dimensional array.
here is my array $array:
[pay] => Array
(
[0] => Array
(
[title] => Array
(
[name] => 'hi'
)
[payment] => Array
(
[amount] => 35
[currency] => USD
)
)
[1] => Array
(
[title] => Array
(
[name] => 'lol'
)
[payment] => Array
(
[amount] => 50
[currency] => USD
)
)
[2] => Array
(
[title] => Array
(
[name] => 'ok'
)
[payment] => Array
(
[amount] => 30
[currency] => USD
)
)
)
i need to get the max value for amount which is 50. how can i do that?
here is what i tried but it did not work:
$max = -9999999; //will hold max val
$found_item = null; //will hold item with max val;
foreach($array as $k=>$v)
{
if($v['Total']>$max)
{
$max = $v['Total'];
$found_item = $v;
}
}
Simple as this one-liner. Get the payment column data, then pull the amount data from that generated array, then get the max value. Done and done. (Sorry it took me so long -- I had to convert your posted array to a usable php array.)
Input:
$array=["pay" => [
["title"=>["name"=>'hi'],"payment"=>["amount"=>35,"currency"=>"USD"]],
["title"=>["name"=>'lol'],"payment"=>["amount"=>50,"currency"=>"USD"]],
["title"=>["name"=>'ok'],"payment"=>["amount"=>30,"currency"=>"USD"]]
]
];
Method #1 (Demo):
echo max(array_column(array_column($array["pay"],"payment"),"amount"));
Method #2 (Demo):
$max=0;
foreach($array["pay"] as $subarray){
if($max<$subarray["payment"]["amount"]){
$max=$subarray["payment"]["amount"];
}
}
echo $max;
Method #3 (Demo):
$payments=array_column($array["pay"],"payment"); // declare payments array
rsort($payments); // sort by amount DESC
echo $payments[0]["amount"]; // access the first amount value
Output:
50
The benefits to method #1 are: code brevity, no condition statements, no global variable declarations/overwriting, just straight to the max value. What's not to love!
If method #1 is too scary, you can go with my method #2 (which was first posted by aendeerei). I don't prefer it because it requires the extra steps of initializing the $max variable, performing a conditional check on each iteration, and overwriting the $max variable when appropriate. Actual performance on the foreach loop is going to depend on the size of your array, but the difference between the two methods is going to be unnoticable to humans.
Method 3 might be my new favorite because there are no conditionals and just two functions before it is accessed purely by keys. However, it does require the declaration of a partial copy of the input array which must be sorted. Anyhow, take your pick -- it's all the same outcome.
Use Usort and get the 1st index
$arr= array
(
array
(
'payment' => array
(
'amount' => 35,
'currency' => 'USD'
)
),
array
(
'payment' => array
(
'amount' => 50,
'currency' => 'USD'
)
),
array
(
'payment' => array
(
'amount' => 80,
'currency' => 'USD'
)
)
);
function sortAmount($x, $y) {
return $y['payment']['amount'] - $x['payment']['amount'];
}
usort($arr, 'sortAmount');
echo "<pre>";
$highest=$arr[0];
print_r($highest)
//for value only
$highest=$arr[0]['payment']['amount'];
Working fiddle
http://phpfiddle.org/main/code/p5hw-ivei
$max = 0;
foreach ($array['pay'] as $key => $item) {
$amount = $item['payment']['amount'];
if ($amount > $max) {
$max = $amount;
}
}
echo $max;
Shorthand:
$result = array_reduce($array['pay'], function($a, $b){
return $a ? ($a['payment']['amount'] > $b['payment']['amount'] ? $a : $b) : $b;
});
var_dump($result['payment']['amount']);
Try this hope this will be helpful. Here we are just using simple foreach to get it done.
Solution 1:
try this code snippet here
$max=0;
foreach($yourArray["pay"] as $value)
{
if($max<$value["payment"]["amount"])
{
$max=$value["payment"]["amount"];
}
}
echo $max;
Solution 2:
Just for testing purpose i have converted you array to json. Here we are using array_column two times to get the columns
Try this code snippet here
$internals=array_column($yourArray["pay"],"payment");//retrieving payments
$amounts=array_column($internals, "amount");//retrieving amounts
arsort($amounts);
print_r(array_values($amounts)[0]);
Consider this example with an array named pay. You can adapt this method for your own array. This code will work for an array of n elements. Here I consider 3 as the number of elements in the array named $pay. You can replace the max elements in the array in the place of 3 for controlling the loop control variable 'i'.
$big=$pay[0];
for($i=1; $i<3; $i++){
if($pay[i]>$big)
$big=$pay[i];
}
echo $big;
I hope this is what you are looking for. Ask for any clarification.
Related
I have a huge array in which keys are also not constant in most of the cases, but there are 3 keys that always constant (#name,#default_value,#value) and #default_value and #value is different i want to get these kind of sub arrays in 1 simple array , for this purpose i am using recursion in whole array and checking out if these 3 keys are present there i can print these values inside recursion easily but I am not able to get those values in return. So that i can precess them further.
$form=array();
$form['field_one']['#name']="field_one";
$form['field_one']['#default_value']="old";
$form['field_one']['#value']="new";
$form['field_two']['#name']="field_two";
$form['field_two']['#default_value']="old";
$form['field_two']['#value']="new";
$form['field_three']['#name']="field_three";
$form['field_three']['#default_value']="old";
$form['field_three']['#value']="old";
$form['thiscouldbeanotherarray']['idk']['field_four']['#name']="field_four";
$form['thiscouldbeanotherarray']['idk']['field_four']['#default_value']="old";
$form['thiscouldbeanotherarray']['idk']['field_four']['#value']="new";
$arr_get = get_updatedvalues($form,array());
var_dump($arr_get);
function get_updatedvalues($form,$fields) {
if (!is_array($form)) {
return;
}
foreach($form as $k => $value) {
if(str_replace('#','',$k) =='default_value' && ($form['#default_value'] != $form['#value'] ) ){
$fields['field'][$form['#name']] = array("name" => $form['#name'],"old_value" =>$form['#default_value'],"new_value" =>$form['#value']);
var_dump($fields);
}
get_updatedvalues($value,$fields);
}
return $fields;
}
If you run this code it will give you $arr_get > array (size=0), there i need all three values
If I understand correctly, you need to pass fields as a reference in order to change it:
function get_updatedvalues($form, &$fields) {
To do that, however, you'll need to change your initial call so that you have a variable to pass as the reference:
$array = [];
$arr_get = get_updatedvalues($form,$array);
Running this I get:
Array
(
[field] => Array
(
[field_one] => Array
(
[name] => field_one
[old_value] => old
[new_value] => new
)
[field_two] => Array
(
[name] => field_two
[old_value] => old
[new_value] => new
)
[field_four] => Array
(
[name] => field_four
[old_value] => old
[new_value] => new
)
)
)
Since this question has a long explanation, I'll ask the question, then have the explanation below -- Can you sort a multidimensional array by their internal array key value, or is there a better way to get around sorting key value pairs that will have inevitable duplicates, than just using an array?
I am mostly unfamiliar with using PHP and want to learn how to store data.
The very simple example I made is just two HTML form inputs for a score and a name and a PHP file to handle the input to be stored in a plain .txt file, which was originally written with the pattern
42|John
32|Jane
25|John
I was able to successfully split the data, sort it, add the new inputted values then store it all back in the text file to be displayed somewhere else, using the name as the key and the score as the value.
I did all this only to realize that it would only store sort and display the last value associated with each name (i.e.)
42|John
32|Jane
25|John
would be sorted to
32|Jane
25|John
because you, obviously, can't have two of the same keys in an array, which is something I completely overlooked.
My solution, currently is to have an extra number that is unique to each name/score pair, which I formatted in the text file as
1|42|John
2|32|Jane
3|25|John
I then split them into a multidimensional array using this foreach loop
foreach($arr as $key => $value) {
$lineData = explode("|", $value);
$scores[$lineData[0]] = array($lineData[1] => $lineData[2]);
}
To get this output
Array
(
[1] => Array
(
[42] => John
)
[2] => Array
(
[32] => Jane
)
[3] => Array
(
[25] => John
)
)
which avoids overwriting any duplicate names or scores, but leaves me in a position where I can't (to my knowledge) use arsort() to sort the array in to highest to lowest.
You can use array_multisort for that, in combination with array_column. Because the key values are strings, you need to also convert them to integers, for which you can use array_map("intval", ...):
foreach($arr as $value) {
$result[] = explode("|", $value);
}
array_multisort(array_map("intval", array_column($result, 0)), $result);
After the above code has run, $result will be sorted by the key values:
[
['25', 'John'],
['32', 'Jane'],
['42', 'John']
]
To reverse the order, apply array_reverse to the result.
Alternative
You could also decide to sort the original array without conversion to a 2D array, and sort it with a custom sort callback, using usort and (again) intval:
usort($arr, function ($a, $b) {
return intval($a) - intval($b);
});
Then $arr will be sorted to:
[
'25|John',
'32|Jane',
'42|John'
]
To reverse the order, switch the position of $a and $b in the sort callback function:
return intval($b) - intval($a);
If we make a small change to your foreach iteration like this:
foreach($arr as $key => $value) {
$lineData = explode("|", $value);
$scores[] = array('score' => $lineData[1], 'name' => $lineData[2]);
}
Your array will have:
Array
(
[0] => Array
(
[score] => 42
[name] => John
)
[1] => Array
(
[score] => 32
[name] => Jane
)
[2] => Array
(
[score] => 25
[name] => John
)
)
You can use the uasort function, which takes the array to sort, and an user-defined function to do the sorting. The code would look like this:
function compare($a, $b)
{
if ($b['score'] == $a['score']) {
if ($a['name'] == $b['name']) {
return 0;
} elseif ($a['name'] < $b['name']) {
return -1;
} else {
return 1;
}
} else {
return ($b['score'] - $a['score']);
}
}
print_r($scores);
uasort($scores, 'compare');
print_r($scores);
Which gives the following result:
Array
(
[1] => Array
(
[score] => 32
[name] => Jane
)
[2] => Array
(
[score] => 25
[name] => John
)
[0] => Array
(
[score] => 42
[name] => John
)
)
When you use a user-defined function for the sorting you need to return one of 3 values (0 of the values as equal, -1 if $a < $b, and 1 if $b > $a. In this case we're sorting first by score (descending), then by name (ascending). Since you need to order from highest to lowest score, the comparison is $b against $a, for ascending order is $a against $b. I didn't consider the extra number necessary. If you need it then change this line:
$scores[] = array('score' => $lineData[1], 'name' => $lineData[2]);
To this:
$scores[$lineData[0]] = array('score' => $lineData[1], 'name' => $lineData[2]);
My Array shown as follows:
Array
(
[0] => Array
(
[amount_id] => 1
[enquiry_id] => 1
[project_id] => 1
)
[1] => Array
(
[amount_id] => 4
[enquiry_id] => 4
[project_id] => 4
)
[2] => Array
(
[amount_id] => 5
[enquiry_id] => 5
[project_id] => 5
)
)
This Array can be increase. How can i get value of each 'amount_id' from this array? What function should i use? Can for each function will work?
Just try with:
$input = array( /* your data */ );
$output = array();
foreach ($input as $data) {
$output[] = $data['amount_id'];
}
You can use a one-liner array_walk() to print those..
array_walk($arr,function($v){ echo $v['amount_id']."<br>";});
Working Demo
Do like this in array_map or Use array_column for The version PHP 5.5 or greater
$outputarr= array_map(function($item){ return $item['amount_id'];},$yourarr);
print_r($outputarr);
Try the following, this is accessing the specific array - easier to debug later on and better speed:
$num=count($your_array);
for($i="0"; $i<$num; $i++)
{
echo $your_array[$i]['amount_id'];
}
you could loop until $i < count($your_array) but it means that the count will run in every loop, for high performance sites I wouldn't do it.
you could access a specific element in a 2D array by $your_array[$the_index]['amount_id'] or other index.
I've got an array like this
Array
(
[0] => Array
(
[0] => Array
(
[szam] => 8
[index] => 0
)
)
[1] => Array
(
[0] => Array
(
[szam] => 1
[index] => 0
)
[1] => Array
(
[szam] => 7
[index] => 1
)
)
I thought that my last cmp will work fine
function maxSzerintCsokkeno($item1,$item2)
{
if ($item1['szam'] == $item2['szam']) return 0;
return ($item1['szam'] < $item2['szam']) ? 1 : -1;
}
with foreach
foreach ($tomb as $kulcs => $adat) usort($adat,"maxSzerintCsokkeno");
but it dosen't do anything, advise?
foreach ($tomb as $kulcs => $adat) usort($adat,"maxSzerintCsokkeno");
This only sorts the subarray array $adat. And this only exists temporarily until foreach loops over the next one. The lazy option here would be to use a reference:
foreach ($tomb as & $adat) usort($adat,"maxSzerintCsokkeno");
Notice the &. This way the modification on $adat will be applied directly in the parent array.
You're sorting a temporary variable, meaning the changes are not applied. The following should work for you:
for($i = 0, $length = count($tomb); $i < $length; $i++)
{
usort($tomb[$i], "maxSzerintCsokkeno");
}
When iterating through the foreach loop, the key and value variables ($kulcs and $adat in your code) are copies of the actual values in the array. Like Tim Cooper said, you are actually sorting a copy of the original value.
You can also pass the value by reference in your foreach loop. This means that you will be modifying the original value:
foreach ($tomb as $kulcs => &$adat) usort($adat,"maxSzerintCsokkeno");
What's the most efficient way to remove items from an array in php where the value is greater than a pre-determined threshold, e.g. given an array
Array
(
[0] => 1.639
[1] => 2.168
[4] => 1.897
[6] => 4.129
)
I would like to remove all the items with a value greater than e.g. 2, preserving key associations, to give
Array
(
[0] => 1.639
[4] => 1.897
)
I know I can do this using a foreach() loop but it seems that there should be a more elegant way.
No matter what you use, the array has to be looped through but you can hide it by using array_filter:
function test($var) { return $var < 2; }
$data = array_filter($data, 'test');