PHP sort multi dimensional array - php

How can I sort this first by Member id and then by Payment date?
Array
(
[240] => Array
(
[Member] => Array
(
[id] => 112
)
[Payment] => Array
(
[date] => 0712
)
)
I tried with multisort, but I never found a way what was working and all examples I found didn't had my additional level.

Is the date value a string or an integer?
Anyway, supposing that date is an int, you could try this:
function my_sort($val1, $val2) {
$compare_id = $val1['Member']['id'] - $val2['Member']['id'];
if($compare_id == 0) {
return $val1['Payment']['date'] - $val2['Payment']['date'];
}
else return $compare_id;
}
and then call:
usort($array, 'my_sort');

If the data is received from database you can use ... ORDER BY member,date

Related

PHP recursive function returning null array

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

Spliting .txt file lines in to multi-layered array key value pairs then sorting it

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]);

Get highest value in multi multidimensional array [duplicate]

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.

Get the max array from an array multidimensional based on value of column

I have this array call $aSumGame :
Array
(
[682] => Array
(
[nature] => 682
[totalGames] => 3
[category] => super
)
[707] => Array
(
[nature] => 707
[totalGames] => 2
[category] => event
)
[728] => Array
(
[nature] => 728
[totalGames] => 2
[category] => event
)
)
Now I want to get the array who have the max number of column totalGames, in this case I want to get the array with the key 682. I tried like this $aMaxGame= max($aSumGame['totalGames']); but not work. Can you help me please ?
You can use uasort along with current function like as
uasort($arr,function($a,$b){
return $b['totalGames'] - $a['totalGames'];
});
print_r(current($arr));
You can simply use usort like as
usort($arr,function($a,$b){
return $b['totalGames'] - $a['totalGames'];
});
print_r($arr[0]);
Demo
Try this
usort($array, function($a, $b) {
return strnatcasecmp($b['totalGames'], $a['totalGames']);
});
print_r(current($array));
Check this, haven`t ran it but should be ok:
$array = array('682'=>array('nature'=>1,'totalGames'=>3), '707'=>array('nature'=>1,'totalGames'=>2));
$tempArray = array();
foreach($array as $id=>$array2) {
$tempArray[$array2['totalGames']][] = $id;// store by the number of games, ex : array('2'=>array(707, 728), '3'=>array(682)
}
$maxKey = max(array_keys($tempArray)); //get the max, ex: 3
var_dump($tempArray[$maxKey]); //all id`s with max, ex: array(682)
list($oneResult) = $tempArray[$maxKey]; //get 682
var_dump($array[$oneResult]); //element from the initial array from key

two php arrays - sort one array with the value order of another

I have two PHP arrays like so:
Array of X records containing the ID
of Wordpress posts (in a particular
order)
Array of Wordpress posts
The two arrays look something like this:
Array One (Sorted Custom Array of Wordpress Post IDs)
Array (
[0] => 54
[1] => 10
[2] => 4
)
Array Two (Wordpress Post Array)
Array (
[0] => stdClass Object
(
[ID] => 4
[post_author] => 1
)
[1] => stdClass Object
(
[ID] => 54
[post_author] => 1
)
[2] => stdClass Object
(
[ID] => 10
[post_author] => 1
)
)
I would like to sort the array of wordpress posts with the order of the ID's in the first array.
I hope this makes sense, and thanks in advance of any help.
Tom
edit: The server is running PHP Version 5.2.14
This should be quite easy using usort, which sorts the array using a user-defined comparison function. The result might look something like this:
usort($posts, function($a, $b) use ($post_ids) {
return array_search($a->ID, $post_ids) - array_search($b->ID, $post_ids);
});
Note that this solution, since it uses anonymous functions and closures, requires PHP 5.3.
One easy solution for this pre-5.3 (the dark ages!) is to do this with a quick loop and then ksort:
$ret = array();
$post_ids = array_flip($post_ids);
foreach ($posts as $post) {
$ret[$post_ids[$post->ID]] = $post;
}
ksort($ret);
You could create a nested looping mechanism to match up the order and ids and rebuild a new post array.
$new_post_array = array();
foreach($id_array as $id) { //loop through custom ordered ids
foreach($post_array as $post) { //for every id loop through posts
if($id == $post->ID){ //and when the custom ordered id matches the post->ID
new_array[] = $post //push the post on the new array
}
}
}
$sortOrderMap = array_flip($postIds);
usort($posts, function($postA, $postB) use ($sortOrderMap) {
return $sortOrderMap[$postA->ID] - $sortOrderMap[$postB->ID];
});
You can simply subtract b from a instead of a from b to sort the other direction

Categories