Sorting lists

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
StumpDK
Forum Commoner
Posts: 35
Joined: Thu Feb 12, 2004 2:28 am
Location: Copenhagen, Denmark

Sorting lists

Post by StumpDK »

I'm creating a website which shows a list of results. The results are in an array.
I wan't the user to be able to sort the list by name, age, city and so on, by clicking on different links.
If 'name' is clicked and are already choosen, the list should sort descending instead of ascending and vice versa.
I've tried with my own code, and I end up with a lot of if-statements that doesn't seem to work.
Do you know any places where I can find examples of such scripts?
Or how would you do?
User avatar
lazy_yogi
Forum Contributor
Posts: 243
Joined: Fri Jan 24, 2003 3:27 am

Post by lazy_yogi »

http://au.php.net/manual/en/function.asort.php

checkout casort in the comments section.
someone made it and does what you want
d3ad1ysp0rk
Forum Donator
Posts: 1661
Joined: Mon Oct 20, 2003 8:31 pm
Location: Maine, USA

Post by d3ad1ysp0rk »

http://lps.no-ip.org/sortsource.php

LOTS of stuff to sift through, but it should give you a basic idea of what I did.

This was one of my first actual big scripts, so it's sloppy, doesn't use functions, and has logic/presentation all jammed up in one big pile of code.

Post here if you have any questions about it.
McGruff
DevNet Master
Posts: 2893
Joined: Thu Jan 30, 2003 8:26 pm
Location: Glasgow, Scotland

Post by McGruff »

You mentioned results - presumably these are obtained from a db query? If so, all you need is an ORDER BY clause.

Best not to put real column names in a link (or a form): switch/case or if/else to map user input to db col names.
StumpDK
Forum Commoner
Posts: 35
Joined: Thu Feb 12, 2004 2:28 am
Location: Copenhagen, Denmark

Post by StumpDK »

Thank you for your replies.
The reason why I'm not using the SQL-query Sort By is, that that would require a DB-query every time someone's sorting their list of results. To optimize the process, I move all of the results into an array, and then I'm doing the sorting.
I've looked at the functions you wrote about, and what I need now, is a function that decides how to the array.
McGruff talks about it's not good to use real coloumn names in a link or a form, but how would you do then?
Is it a switch:

switch($_GET['sort_by'])
case 'name':
<< Sorting by name >>

case 'age':
<< Sorting by age >>

Or how would you do it?
User avatar
markl999
DevNet Resident
Posts: 1972
Joined: Thu Oct 16, 2003 5:49 pm
Location: Manchester (UK)

Post by markl999 »

How are you storing the array inbetween page requests?
ie if you don't redo the query then how is the array 'regenerated', are you storing it in a session or something?
StumpDK
Forum Commoner
Posts: 35
Joined: Thu Feb 12, 2004 2:28 am
Location: Copenhagen, Denmark

Post by StumpDK »

Yes... I'm using the $_SESSION to store the array between the pages...
User avatar
markl999
DevNet Resident
Posts: 1972
Joined: Thu Oct 16, 2003 5:49 pm
Location: Manchester (UK)

Post by markl999 »

Here's an example that uses a hardcoded array, but you should be able to adapt it to your array/rows from the db.

Code: Select all

<?php
session_start();

//list of columns titles, this makes the links easier
$columns = array('fname', 'lname');

//set the array if it's not already in the session
if(empty($_SESSION['list'])){
    $_SESSION['list'] = array(
        array('fname' => 'john', 'lname' => 'doe'),
        array('fname' => 'zak', 'lname' => 'bloggs'),
        array('fname' => 'john3', 'lname' => 'doe3')
    );
}
//set the default order
$order = SORT_DESC;
//see if we need to 'flip' the order
if(!empty($_GET['sort_by'])){
    if(substr($_GET['sort_by'], 0, 1) == 'd'){
        $order = SORT_DESC;
    } else {
        $order = SORT_ASC;
    }
    $by = substr($_GET['sort_by'], 1);
} else {
    $_GET['sort_by'] = 'fname';
}
//sort it
array_multisort($_SESSION['list'], $order);

//display it
?>
<table>
    <tr>
    <?php
    foreach($columns as $col){
        $link = ($_GET['sort_by'] == $col) ? 'd'.$col : $col;        
        echo '<td><a href="'.$_SERVER['PHP_SELF'].'?sort_by='.$link.'">'.$col.'</a></td>';
    }
    ?>
    </tr>
    <?php
    foreach($_SESSION['list'] as $row){
        echo '<tr><td>'.$row['fname'].'</td><td>'.$row['lname'].'</td></tr>';
    }
    ?>
</table>
StumpDK
Forum Commoner
Posts: 35
Joined: Thu Feb 12, 2004 2:28 am
Location: Copenhagen, Denmark

Post by StumpDK »

Well, thanks alot! That code is very usefull...
What is your opinion on me choice of using a session-array instead of the DB-query?
redmonkey
Forum Regular
Posts: 836
Joined: Thu Dec 18, 2003 3:58 pm

Post by redmonkey »

Not sure if it's of any use but here is my non-casesensitive sorting function....

Code: Select all

function array_ncsort($array, $index, $flag = SORT_ASC)
{
  for($i = 0, $asize = count($array); $i < $asize; $i++)
  {
    $sortarr[] = strtolower($array[$i][$index]);
  }

  array_multisort($sortarr, $flag, $array);

  return($array);
}
Example usage.....

Code: Select all

$names = array(
          array('fname' => 'Frank', 'lname' => 'Smith', 'age' => 25),
          array('fname' => 'John',  'lname' => 'Doe', 'age' => 28),
          array('fname' => 'Joe',   'lname' => 'Bloggs', 'age' => 32),
          array('fname' => 'Able',  'lname' => 'Jones', 'age' => 24)
         );

// sort by firstname A => Z
$sorted = array_ncsort($names, 'fname');

// sort by lastname Z => A
$sorted = array_ncsort($names, 'lname', SORT_DESC);
magicrobotmonkey
Forum Regular
Posts: 888
Joined: Sun Mar 21, 2004 1:09 pm
Location: Cambridge, MA

Post by magicrobotmonkey »

To optimize the process, I move all of the results into an array, and then I'm doing the sorting.
I'm not sure if that's an optimization for a couple of reasons.

1. DB's are designed for that sort of thing. I think it would take a lot less work for a bunch of queries using ORDERBY rather than some php sorting algorithm which will require a lot of memory (double the size of the array?) and a good bit of processing, whereas the DB is optimized for such things.

2. A large array like that will use a bunch of memory when passed from page to page.

I dunno, but on this one, I'd let the DB do the work. By the way, what sort algorithm are you using?
StumpDK
Forum Commoner
Posts: 35
Joined: Thu Feb 12, 2004 2:28 am
Location: Copenhagen, Denmark

Post by StumpDK »

Nice comments to the sorting thing. I'm not very much in to all this sorting thing, so I'm using array_multisort, but honestly, I don't know which one to use... Any ideas?
McGruff
DevNet Master
Posts: 2893
Joined: Thu Jan 30, 2003 8:26 pm
Location: Glasgow, Scotland

Post by McGruff »

usort()

You'll need a callback function for each column you wish to sort on.
d3ad1ysp0rk
Forum Donator
Posts: 1661
Joined: Mon Oct 20, 2003 8:31 pm
Location: Maine, USA

Post by d3ad1ysp0rk »

I'd use SQL ORDERBY. Much faster.
Post Reply