tags:

views:

166

answers:

4

I have a file here which contains list of database names and its corresponding size. Now I want to sort the size from the largest to the lowest, and the database name should go along it upon display.Am using PHP here.. Can anyone help me out?

Here's a simple code for that:

$file_name = test.txt
$handle = @fopen($file_name, "r");

if ($handle) {
    while (!feof($handle)) {

    $buffer = fgets($handle, 4096);
        $data = explode(" ",$buffer);
       echo $data[1]."\n";
    }
    fclose($handle);
}

File looks like this:

DatabaseName 300 KB

Note: $data[1] contains the sizes. Should i place it on an array? how about the db name?

Answers are very much appreciated. =)

+2  A: 

First you need to build an array with an element you can actually sort on, then use usort or similar to perform the sort based on your custom criteria.

//first build up an array of databases with a unified size in bytes, ensuring
//we account for those postfixes like KB,MB,and GB
$databases=array();
while (!feof($handle)) {

    $buffer = fgets($handle, 4096);
    $data = explode(" ",$buffer);
    if (count($data)==3)
    {
        $size=$data[1];
        switch ($data[2])
        {
            case 'KB': $size*=1024; break;
            case 'MB': $size*=1024*1024; break;
            case 'GB': $size*=1024*1024*1024; break;
        }

        $data[3]=$size;
        $databases[]=$data; 
    }
    else
    {
        die("Bad line in file: $buffer");
    }
}

Now sort with a custom comparison function to sort from high to low based on that calculated size:

function cmp($a, $b)
{
    if ($a[3] == $b[3]) {
        return 0;
    }
    return ($a[3] < $b[3]) ? 1 : -1;
}

usort($databases, "cmp");
Paul Dixon
You can write that `switch` in a more compact way: `switch ($data[2]) { case 'GB': $size*=1024; case 'MB': $size*=1024; case 'KB': $size*=1024; }`.
Gumbo
+1  A: 
function databases_sort($a, $b) {
    if ($a[1] == $b[1]) { return 0; }

    return ($a[1] < $b[1]) ? -1 : 1;
}

$file_name = "test.txt";
$handle = @fopen($file_name, "r");

$databases = array();

if ($handle) { 
    while (!feof($handle)) {

        $buffer = fgets($handle, 4096);
        $data = explode(" ",$buffer);
        $databases[] = $data;
    //echo $data[1]."\n";
    }

    usort($databases, "databases_sort");

    foreach ($databases as $d) {
        echo $d[1];
    }

    fclose($handle);
}

This code stores your information in an array, then runs a custom sorting function on your array, sorting it by the value of element 1 in the array. Higher values (larger database sizes) get sorted to the top of the list.

Warning: I haven't actually tested this code, but you can see the usort documentation if there are any bugs that need fixing.

Edit: d'oh, beaten by a few seconds :-)

Rob Knight
minor point, but you've done an ascending rather than descending sort :)
Paul Dixon
Whoops, that's why copying and pasting code is always a silly thing to do!
Rob Knight
+2  A: 

You can use the file() PHP function here.

Your text file is like :

DatabaseName 300 KB
DatabaseName 300 KB
DatabaseName 300 KB
DatabaseName 300 KB

I think you can use the PHP native function on arrays.

$data = file('myfile.txt');

foreach($data as $one_line)
{
    $db[] = explode(" ",$one_line)
    //will have $db[0][0] = 'dbname';
    //will have $db[0][2] = '30';
    //will have $db[0][2] = 'KB'; 
    //will have $db[1][0] = 'dbname';
    //will have $db[1][3] = '30';
    //will have $db[1][2] = 'KB';
}
array_multisort($db[1], SORT_NUMERIC, SORT_DESC);

See this comment in documentation, the same structure : http://fr2.php.net/manual/en/function.array-multisort.php#79491

Or maybe you have to flip the array, so you can have size in index and name in value.

mere-teresa
that's a nice compact solution, but does require that the size is always in KB (which may be the case, the OP didn't specify).
Paul Dixon
Yes, your solution with the switch is interesting too.I wanted to use PHP native functions.
mere-teresa
A: 

Have you thought about parsing into a binary search tree structure instead of an array? That way you could have the data sorted with a tree traversal and you could have fast lookup too.

Robert