Jump to content
NFreak

How to Sort a 2d Array With Php?

Recommended Posts

I've looked up various PHP functions like asort() and arsort(), but I can't seem to find a way to sort an array by a specified dimension. For example:

 

$arrStats=array();

 

$arrStats[1][attack]=150;

$arrStats[2][attack]=200;

$arrStats[3][attack]=75;

 

$arrStats[1][defense]=250;

$arrStats[2][defense]=50;

$arrStats[3][defense]=980;

 

I can't seem to find a function that sorts by a specified type. I programmed a game for my website, and every 30 minutes I have a cron script run that ranks all the users by various stats (attack, defense, spy, sentry). The script used to be able to run almost instantly, but then membership grew to 500, and it started slowing down. Now, membership for my game is at about 1800 in the past 2 months, and the update takes literally 15 minutes to load. The update goes every 30 minutes, so that basically means there is a massive script running 50% of the time. This causes a lot of lag near midnight, when the daily update goes off.

 

So, my question is, does anyone know if a quick way to sort out an array. In this example, I'd like to be able to sort the array out by attack power, and then by defense power, as quickly as possible.

 

Any help, or suggestions?

 

Thanks. :)

Share this post


Link to post
Share on other sites

Thanks for the suggestions. If you're able to provide some sample code to sort the above array by attack and defense, that would be great. :)

 

I'm not sure how I would apply the suggested functions to my script. :)

 

$arrStats=array();

 

$arrStats[1][username]="Bob";

$arrStats[2][username]="Bill";

$arrStats[3][username]="John";

 

$arrStats[1][attack]=150;

$arrStats[2][attack]=200;

$arrStats[3][attack]=75;

 

$arrStats[1][defense]=250;

$arrStats[2][defense]=50;

$arrStats[3][defense]=980;

 

Basically, John's attack power is 75, and his defense power is 980. He's ranked first for defense, but third for attack. That's what I need to do. The current way I do it involves a massive nested loop that is killing my bandwidth, as it's sorting over 1800 users every 30 minutes.

 

The most basic sorting function, sort($array), works almost perfectly. The only problem is that it sorts by the first type listed in the second dimension. So, since username was first declared, it will sort by username. If there's a way to make it sort by attack and defense, that would work perfectly.

Edited by NFreak

Share this post


Link to post
Share on other sites

I got my update to finish in 5 minutes, up from about 12 - 15.

 

All I did was combine a line of code with another. I had no idea that writing to a database took so much time.

 

I had two lines of code next to each other that updated the users gold, then gave the user an extra turn.

 

I made it give the user gold and a turn in the same line of code, and somehow that cut about 10 minutes off the update time. I suppose that looping a bunch of mysql code 1800 times goes much faster when there aren't two update lines next to each other. I'm satisfied with update time, and I shouldn't have any further problems unless membership reaches about 3500.

Share this post


Link to post
Share on other sites

><?php

$arrStats=array();

$arrStats[1]['username']="Bob";
$arrStats[2]['username']="Bill";
$arrStats[3]['username']="John";

$arrStats[1]['attack']=150;
$arrStats[2]['attack']=200;
$arrStats[3]['attack']=75;

$arrStats[1]['defense']=250;
$arrStats[2]['defense']=50;
$arrStats[3]['defense']=980;


function Defense($a, $b)
{
   	if ($a['defense'] == $b['defense']) {
	return 0;
	}
return ($a['defense'] > $b['defense']) ? -1 : 1;
}
			
function Attack($a, $b)
{	   
	if ($a['attack'] == $b['attack']) {
return 0;
}	
return ($a['attack'] > $b['attack']) ? -1 : 1;
}	  



usort($arrStats, "Defense");
while (list($key, $value) = each($arrStats)) {
   echo $value["username"] . " (Defense: " . $value["defense"] . ")\n";
   }
   


usort($arrStats, "Attack");
echo "\n";
while (list($key, $value) = each($arrStats)) {
   echo $value["username"] . " (Attack: " . $value["attack"] . ")\n";
   }
echo "\n";				  
?>

 

See how that works out for ya.

 

Edit: The only problem for me is if two usernames have the same attack as each other (or defense), then they are sorted randomly and not alphabetically.

Also, if you are outputting this as html, of course every instance of "\n" should be <br>.

Edited by Steve Scrimpshire

Share this post


Link to post
Share on other sites

I tested this on my linux box at home (Intel 2.66 GHz with 512 MB RAM) and the script uses 30% CPU for .95 seconds with 1800 users in the array.

Edited by Steve Scrimpshire

Share this post


Link to post
Share on other sites

Wow, that's amazing. I tested it and it worked. Now I just have to implement that into my script. Thank you very much. I have one question, though.

 

return ($a['defense'] > $b['defense']) ? -1 : 1;

 

What does that line of code do? I don't understand the "? -1 : 1;". I've never seen anything like that before. :D

Share this post


Link to post
Share on other sites

Alright, I got my script up and running. You rock!

 

The script takes about 3.5 - 4 minutes to run, but it does a lot.

 

It gives every member of the site some gold and an extra attack turn. Then it proceeds to find out the four minor ranks (attack, defense, spy, sentry). After it writes all of that to the database it adds together the attack, defense, spy, and sentry ranks into a new array.

 

So if my stats are:

 

Attack: Ranked #40

Defense: Ranked #108

Spy: Ranked #1231

Sentry: Ranked #430

 

It would add (40+108+1231+430) into a new variable. It does that for every user, then sorts it out in reverse to find the overall rank. So the number 1 member will have the lowest number when all the ranks are added.

 

The reason it takes so long is because writing to the database is slow. At least it seems that way. But 3.5 minutes up from 12 clears up a lot of lag, makes it less glitchy, and saves loads of bandwidth.

 

*Bows down.*

Share this post


Link to post
Share on other sites

Actually, scratch that. The update takes about 2.5 minutes to update. This owns. I may never have to revise this code again. :D

Share this post


Link to post
Share on other sites
Wow, that's amazing. I tested it and it worked. Now I just have to implement that into my script. Thank you very much. I have one question, though.

 

return ($a['defense'] > $b['defense']) ? -1 : 1;

 

What does that line of code do?

 

This is a concise way to say:

 

if ($a['defense'] > $b['defense'])

return -1;

else

return 1;

Share this post


Link to post
Share on other sites

Okay, cool.

 

I'm new to functions and stuff. I've never used return before.

Share this post


Link to post
Share on other sites

You also may want to consider selecting it from your database in the order you want. I'm assuming you are using MySQL:

>SELECT Username,  Attack, Defense, Spy, Sentry FROM Users
ORDER BY Attack, Username

 

This should start the new array sorted by attack and if two users have the same attack rating, they are sorted alphabetically.

Share this post


Link to post
Share on other sites

Selected them from the database sorted the way you want should do away with the need for a cron script (except the cron script to update the database with new values, of course) and they are sorted dynamically.

 

My apologies if this is not what you are intending.

Edited by Steve Scrimpshire

Share this post


Link to post
Share on other sites

I don't actually store the values for attack, defense, spy, and sentry in the database. The database stores the values for how many of each item the user has, the number of trained soldiers, etc...

 

It pulls that information and generates the attack, defense, etc... stats as it loads the page. Otherwise grabbing it already sorted would've been easy.

 

Thank you again for all the help. The script is so fast now. -_-

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...