3

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

5 Answers 5

2

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");
Sign up to request clarification or add additional context in comments.

1 Comment

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; }.
2

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 : https://www.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.

2 Comments

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).
Yes, your solution with the switch is interesting too. I wanted to use PHP native functions.
1
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 :-)

2 Comments

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

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.

1 Comment

Was this answer meant to be a comment? It is asking a question and giving a hint.
0

From the very start, parse your lines into meaningful components. Calculate the bytes per database and save as a related array to the array of database lines. Use a lookup array to facilitate byte calculations. Finally, sort the db names array according to the bytes totals. Demo

$handle = fopen($file_name, "r")

$powers = ['B' => 0, 'KB' => 1, 'MB' => 2, 'GB' => 3, 'TB' => 4];
$bytes = [];
$names = [];
while (fscanf($handle, '%s %d %s', $name, $size, $unit) === 3) {
    $bytes[] = $size * 1024 ** $powers[strtoupper($unit)];
    $names[] = "$name $size $unit";
}
fclose($handle);

array_multisort($bytes, SORT_DESC, $names);
var_export($names);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.