Sort array using multiple criteria in PHP [duplicate] - php

This question already has answers here:
How can I sort arrays and data in PHP?
(14 answers)
Closed 8 years ago.
I know there are some other topics about sorting with multiple criteria, but they don't fix my problem.
Let's say I have this array:
Array
(
[0] => Array
(
[uid] => 1
[score] => 9
[endgame] => 2
)
[1] => Array
(
[uid] => 2
[score] => 4
[endgame] => 1
)
[2] => Array
(
[uid] => 3
[score] => 4
[endgame] => 100
)
[3] => Array
(
[uid] => 4
[score] => 4
[endgame] => 70
)
)
I want to sort it, putting the one with the HIGHEST score on top. On same score, I want the one with the LOWEST endgame number on top.
The sorting mechanisme should rank user1 on top, then user2, then 4 and then user3.
I use this sorting mechanisme:
function order_by_score_endgame($a, $b)
{
if ($a['score'] == $b['score'])
{
// score is the same, sort by endgame
if ($a['endgame'] == $b['endgame']) return 0;
return $a['endgame'] == 'y' ? -1 : 1;
}
// sort the higher score first:
return $a['score'] < $b['score'] ? 1 : -1;
}
usort($dummy, "order_by_score_endgame");
This gives me the following array:
Array
(
[0] => Array
(
[uid] => 1
[score] => 9
[endgame] => 2
)
[1] => Array
(
[uid] => 3
[score] => 4
[endgame] => 100
)
[2] => Array
(
[uid] => 2
[score] => 4
[endgame] => 1
)
[3] => Array
(
[uid] => 4
[score] => 4
[endgame] => 70
)
)
As you can see, the array isn't sorted properly... Anyone knows what I'm doing wrong? Thanks a lot!

Your function should be like this:
function order_by_score_endgame($a, $b) {
if ($a['score'] == $b['score']) {
// score is the same, sort by endgame
if ($a['endgame'] > $b['endgame']) {
return 1;
}
}
// sort the higher score first:
return $a['score'] < $b['score'] ? 1 : -1;
}
Try it out. It will give you result like this:
Array
(
[0] => Array
(
[uid] => 1
[score] => 9
[endgame] => 2
)
[1] => Array
(
[uid] => 2
[score] => 4
[endgame] => 1
)
[2] => Array
(
[uid] => 4
[score] => 4
[endgame] => 70
)
[3] => Array
(
[uid] => 3
[score] => 4
[endgame] => 100
)
)

Related

php combine two array's subarrays where value of certain key is equal

Hello & thanks for your interest
I do have two arrays:
[A] -from the mysql query of one database on server1- the
$postings_array - a SELECT of all postings of a discussion-thread
(based on the thread's id)
[B] -from the mysql query of an other database on server2 - the
$usersdata_array - a SELECT of all postings of a discussion-thread
(based on the thread's id)
This means:
in [A] there are many postings-sub-arrays and in [B] one or more
userdata-sub-arrays.
both arrays always do include a key named usrsID in each of their
subarrays.
I need to extend the Sub-Arrays in $postings_array [A]
by merging them
with the Sub-Arrays of the $usersdata_array [B]
based on WHERE the VALUE of the usrsID KEY in the sub-array[A] is EQUAL to the usrsID KEY in the sub-array[B].
EXAMPLE:
Array [A]:
(
[0] => Array
(
[ID] => 5
[usrsID] => 3
[tid] => 19
[txtid] => 22
)
[1] => Array
(
[ID] => 6
[usrsID] => 1
[tid] => 19
[txtid] => 23
)
[2] => Array
(
[ID] => 7
[usrsID] => 2
[tid] => 19
[txtid] => 24
)
[3] => Array
(
[ID] => 8
[usrsID] => 1
[tid] => 19
[txtid] => 25
)
)
--
Array [B]:
(
[0] => Array
(
[id] => 1
[usrsID] => 1
[avatarID] => 1
)
[1] => Array
(
[id] => 2
[usrsID] => 2
[avatarID] => 3
)
[2] => Array
(
[id] => 3
[usrsID] => 3
[avatarID] => 22
)
)
needed result (the by [B] extended [A] for the example above):
Array [A_extended]:
(
[0] => Array
(
[ID] => 5
[usrsID] => 3
[tid] => 19
[txtid] => 22
[id] => 3
[avatarID] => 22
)
[1] => Array
(
[ID] => 6
[usrsID] => 1
[tid] => 19
[txtid] => 23
[id] => 1
[avatarID] => 1
)
[2] => Array
(
[ID] => 7
[usrsID] => 2
[tid] => 19
[txtid] => 24
[id] => 2
[avatarID] => 3
)
[3] => Array
(
[ID] => 8
[usrsID] => 1
[tid] => 19
[txtid] => 25
[id] => 1
[avatarID] => 1
)
)
... I think, it's a common problem so there should be a best-practice around (may be in one inbuild php function or a combination of two or three of them) - and I do not have to reinvent the wheel.
At least, I hope so...
else, my approach would be
check the amounts of iterations (= the subarrays found in the $usersdata_array [B] )
iterate over the outerHaystack and trigger a function when $needle was found in innerHaystack
perform merge via checkSubArrayfunc
Approach,
with hayStackArray = complete [A]Array;
needle = $usrsID value of [B] Sub-Array:
function checkSubArrayfunc($hayStackSubArray, $needle, $toMergeSubArray) {
if (in_array(array('$hayStackSubArray'), $needle)) {
array_merge_recursive($hayStackSubArray, $toMergeSubArray);
}
}
Try this:
foreach($arr_b as $b_item) {
foreach($arr_a as $key => &$a_item) {
if ($b_item['usrsID'] == $a_item['usrsID']) {
$a_item['id'] = $b_item['usrsID'];
$a_item['avatarID'] = $b_item['avatarID'];
}
}
}
Your output of $_arr_a will be:
Array
(
[0] => Array
(
[ID] => 5
[usrsID] => 3
[tid] => 19
[txtid] => 22
[id] => 3
[avatarID] => 22
)
[1] => Array
(
[ID] => 6
[usrsID] => 1
[tid] => 19
[txtid] => 23
[id] => 1
[avatarID] => 1
)
[2] => Array
(
[ID] => 7
[usrsID] => 2
[tid] => 19
[txtid] => 24
[id] => 2
[avatarID] => 3
)
[3] => Array
(
[ID] => 8
[usrsID] => 1
[tid] => 19
[txtid] => 25
[id] => 1
[avatarID] => 1
)
)
At first take an empty array for store marged array. then traversed in both array. if the userID are be same in both the array of element then marge these array and push in margeArr.
$margeArr = [];
foreach($Array_A as $a){
foreach($Array_B as $b){
if($a['usrsID'] == $b['usrsID']){
array_push($margeArr,array_merge($a,$b));
}
}
}
print_r($margeArr);
Comment by the questionaire:
It's a great solution - it really meets the requirements described in my question and merges the to be marged Array with the key-value-pairs of the "to be injected"-Array.
But I prefere the bestprogrammersinintheworld's solution, where I can rename the keys "en passant / on-the-fly":
foreach($arr_b as $b_item) {
foreach($arr_a as $key => &$a_item) {
if ($b_item['usrsID'] == $a_item['usrsID']) {
$a_item['myNewKeyName1'] = $b_item['usrsID'];
$a_item['myNewKeyName2'] = $b_item['avatarID'];
}
}
}
print("<pre>".print_r($arr_a,true)."</pre>");
Sorting my advice from best to worst...
Joining this data should be done before PHP is necessary. Depending on the location of the two sources, this may be trivial, but JOINing via SQL is the best, most direct, most professional option. These links may be helpful:
access two different databases on different servers in the same query
Joining Tables from different Database
In lieu of option 1, declare and leverage a lookup array (in PHP) which would have the identifying column as its first level keys. Then you don't need to nest another loop to relate the two data sets.
$lookup = array_column($arrayB, null, 'usrsID');
foreach ($arrayA as $row) {
$result[] = $row + ($lookup[$row['usrsID']] ?? []);
}
The worst option which I do NOT recommend is writing a nested loop with a condition inside of it. All previous answers are doing this -- and slowing down an already inefficient approach, they don't even break inside the condition block.

PHP - Sort Multidimensional Array by string [duplicate]

This question already has answers here:
How can I sort arrays and data in PHP?
(14 answers)
How to compare 2 strings alphabetically in PHP?
(5 answers)
Closed 5 years ago.
I have an array called "$myarray", which looks like this:
[0] => Array
(
[PrinterID] => 4
[PrinterName] => PRT04_GL
[UserID] => 1
[isDefaultPrinter] => 0
[isMapped] => 0
)
[1] => Array
(
[PrinterID] => 1
[PrinterName] => PRT01_Zentral
[UserID] =>
[isDefaultPrinter] => 0
[isMapped] => 0
)
[2] => Array
(
[PrinterID] => 2
[PrinterName] => PRT02_BH
[UserID] =>
[isDefaultPrinter] => 0
[isMapped] => 0
)
[3] => Array
(
[PrinterID] => 3
[PrinterName] => PRT03_EDV
[UserID] =>
[isDefaultPrinter] => 0
[isMapped] => 1
)
I want to sort the data by ["PrinterName"]. The wanted result would be:
[0] => Array
(
[PrinterID] => 1
[PrinterName] => PRT01_Zentral
[UserID] =>
[isDefaultPrinter] => 0
[isMapped] => 0
)
[1] => Array
(
[PrinterID] => 2
[PrinterName] => PRT02_BH
[UserID] =>
[isDefaultPrinter] => 0
[isMapped] => 0
)
[2] => Array
(
[PrinterID] => 3
[PrinterName] => PRT03_EDV
[UserID] =>
[isDefaultPrinter] => 0
[isMapped] => 1
)
[3] => Array
(
[PrinterID] => 4
[PrinterName] => PRT04_GL
[UserID] => 1
[isDefaultPrinter] => 0
[isMapped] => 0
)
Based on this example I tried the following:
uasort($myarray, 'sort_by_order');
function sort_by_order ($a, $b) {
return $a['PrinterName'] - $b['PrinterName'];
}
This does not work. I get errors like "A non-numeric value encountered ...", of course because my values are strings and the function is for numeric values.
How do I sort the array?
Thank you!
EDIT:
I think I did find the solution here. I used this and it seems to work:
uasort($myarray, 'sort_by_order');
function sort_by_order ( $a, $b ) { return strcmp($a['PrinterName'], $b['PrinterName']); }
Please try with $a['PrinterName'] > $b['PrinterName']
It will compare the values

PHP match values between 2 arrays not same key

I have made researches and havent fount any solutions for this yet. So final thought is come to Stackoverflow and ask the question.
I have 2 array like below:
BigArray
Array
(
[0] => Array
(
[id] => 1
[category_name] => Accountancy
[category_name_vi] => Kế toán
[category_id] => 1
)
[1] => Array
(
[id] => 2
[category_name] => Armed forces
[category_name_vi] => Quân đội
[category_id] => 2
)
[2] => Array
(
[id] => 3
[category_name] => Admin & Secretarial
[category_name_vi] => Thư ký & Hành chính
[category_id] => 3
)
[3] => Array
(
[id] => 4
[category_name] => Banking & Finance
[category_name_vi] => Tài chính & Ngân hàng
[category_id] => 4
)
)
and SmallArray:
Array
(
[0] => Array
(
[id] => 7
[category_id] => 2
[jobseeker_id] => 1
)
[1] => Array
(
[id] => 8
[category_id] => 3
[jobseeker_id] => 1
)
)
Ok, now I wanted to match each category_id from SmallArray link with respectively category_name from BigArrayand the output I only need matched values between SmallArray and BigArraywhere category_id of SmallArray is key and category_name of BigArray is value like below:
Matched array:
Array
(
[0] => Array
(
[2] => Armed forces
)
[1] => Array
(
[3] => Admin & Secretarial
)
)
So far, I have tried array_intersect, 2 foreach loops but no luck. Any advise would be very appreciated :(
Thanks
This should do that:
foreach ($smallArray as $smallKey => $smallElement) {
foreach ($bigArray as $bigKey => $bigElement) {
if ($bigElement['id'] == $smallElement['category_id']) {
$smallArray[$smallKey] = array(
$bigElement['id'] => $bigElement['category_name'],
);
break; // for performance and no extra looping
}
}
}
After these loops, you have what you want in $smallArray.

Search an array[key] for any integer but one

I am currently stumped while searching for an answer, but I have an array which contains information relating to a tournament, as seen below.
I would like to search through this Array of arrays for specifically the opponent key, and determine if they are all -2. This is because the logic is that -2 is a bye, so if all people have -2 as their opponent, this means that all brackets have been finished.
My initial thought was just do an array_search(!(-2), $anArray), but that obviously didn't work and I hit myself on the head for thinking it would be that easy haha. Thanks.
EX:
Array (
[0] => Array ( [dId] => 11 [uId] => 3 [id] => 1 [round] => 0 [opponent] => 3 [bracket] => 0 )
[1] => Array ( [dId] => 11 [uId] => 5 [id] => 2 [round] => 0 [opponent] => -2 [bracket] => 1 )
[2] => Array ( [dId] => 11 [uId] => 10 [id] => 3 [round] => 0 [opponent] => 1 [bracket] => 0 ) )
This function will return true if all opponents are -2 and false if there is a single opponent != -2:
function all_opponent_search($arr){
for($i = 0; $i < count($arr); $i++)
if($arr[$i]['opponent'] != -2)
return false;
return true;
}
how about:
foreach ($masterArray as $subArray) {
if (isset($subArray['opponent']) && ($subArray['opponent'] == -2)) {
// do whatever you need
}
}

Sorting Multidimensional Array by Specific Key

EDIT: For anyone who might come across this post with a similar problem, It was solved by taking konforce's supplied answer and tweaking around a bit with the custom sorting function:
function cmp($a, $b) {
if ($a[5] == $b[5]) {
return ($a[3] < $b[3]) ? -1 :1;
}
return ($a[5] > $b[5]) ? -1 : 1;
}
Notice $a[5] == $b[5] does not return zero. It was changed to check who has the most losses and then sort it in ASC order. I'm sure you can even keep going and add another if-statement in there in-case they have the same losses.
Lastly, all you do is usort($ARRAY, "cmp"); and finito!!!
Original Post
My apologies for coming up with yet another MD Array sorting question but I'm just not getting it. I've searched aplenty
for a solution and although many sites have provided what seemed like a logical answer I still have not been able to figure it out.
My problem is since I'm still learning its been rather difficult for me to grasp the concept of using usort with a custom comparing
function. Atleast, thats what I have seen the most when others have tried to sort MD Arrays.
I'm working on a small project to sharpen up on my php skills. Its a very basic tournament standings script that holds a team's information within an array. I would like to sort the array by most points($array[X][X][5]).
So the array looks something like this:
Array (
[0] => Array (
[0] => Array (
[0] => cooller
[1] => 6
[2] => 6
[3] => 0
[4] => 0
[5] => 18
)
)
[1] => Array (
[0] => Array (
[0] => strenx
[1] => 9
[2] => 5
[3] => 1
[4] => 3
[5] => 18
)
)
[2] => Array (
[0] => Array (
[0] => rapha
[1] => 10
[2] => 8
[3] => 1
[4] => 1
[5] => 25
)
) [3] => Array (
[0] => Array (
[0] => ronald reagan
[1] => 5
[2] => 4
[3] => 0
[4] => 1
[5] => 13
)
)
)
I would like to sort it by most points(cell #5), so it would look like this after sorting:
Array (
[0] => Array (
[0] => Array (
[0] => rapha
[1] => 10
[2] => 8
[3] => 1
[4] => 1
[5] => 25
)
)
[1] => Array (
[0] => Array (
[0] => cooller
[1] => 6
[2] => 6
[3] => 0
[4] => 0
[5] => 18
)
)
[2] => Array (
[0] => Array (
[0] => strenx
[1] => 9
[2] => 5
[3] => 1
[4] => 3
[5] => 18
)
)
[3] => Array (
[0] => Array (
[0] => ronald reagan
[1] => 5
[2] => 4
[3] => 0
[4] => 1
[5] => 13
)
)
)
The player with 25 points would be at the top, followed by 18, 18, and lastly 13. Sorry for my earlier post, was having difficulty wording my question correctly. Thanks in advanced!
I think you want something like this:
usort($standings, function($a, $b) { return $b[0][5] - $a[0][5]; });
Or prior to PHP 5.3:
function cmp($a, $b) { return $b[0][5] - $a[0][5]; }
usort($standings, 'cmp');
When using usort, the $a and $b parameters will be one "layer" into the supplied array. So in your case, an example of $a or $b will be:
[0] => Array (
[0] => cooller
[1] => 6
[2] => 6
[3] => 0
[4] => 0
[5] => 18
)
I'm not sure why you have an extra containing array there, but as you can see, you want to sort based on the [0][5] position.
usort($standings[0][0][5], 'cmp') won't work because the first parameter isn't an array to sort, it's just a single number, the points.

Categories