-1

I am using a text file as little database, and each line has this format:

3692|Giovanni|giojo982|0005405
9797|Stefano|stefy734|45367
2566|Marco|markkkk998|355647689
4721|Roberto|robn88|809678741

I need to order them alphabetically maintaining their indexes, if it's possible. At the moment, I'm using this code, but in this situation logically it doesn't work any more.

Reading this post How can I sort arrays and data in PHP? I have not found nothing similar to my scenario. So, I'm wondering... is there a solution?

$db_friends = "db_friends.txt";
$dblines = file($db_friends);

if(isset($_GET['A-Z'])) {
    asort($dblines);
}
if(isset($_GET['Z-A'])) {
    arsort($dblines);
}

foreach($dblines as $key => $profile) {
    list($uni_id, $name_surname, $textnum_id, $num_id) = explode("|", $profile);
    echo $name_surname;
}

<a href="./?A-Z">A-Z</a>
<a href="./?Z-A">Z-A</a>

How can I solve it?

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
Devilix
  • 334
  • 3
  • 13

4 Answers4

3

I assume by alphabetically that you're trying to sort alphabetically by the name in the second column. The problem is, asort() and arsort() perform too simple a comparison to deal with the type of data you're giving them. They're just going to see the rows as strings, and sort by the number in the first column. One way to address this is by splitting the rows before sorting.

$db_friends = "db_friends.txt";
$dblines = file($db_friends);

// split each line into an array
$dblines = array_map(function($line){ 
    return explode('|', $line); 
}, $dblines);

Then you can sort by the second column more easily. Using uasort(), you'll maintain the index association.

if (isset($_GET['A-Z'])) {
    uasort($dblines, function(array $a, array $b) {
        return strcmp($a[1], $b[1]);
    });
}

if (isset($_GET['Z-A'])) {
    uasort($dblines, function(array $a, array $b) {
        return strcmp($b[1], $a[1]);
    });
}

Obviously if you make that change, you'll no longer need to explode when you iterate the sorted array, as it was already done in the first step.

foreach ($dblines as $key => $profile) {
    list($uni_id, $name_surname, $textnum_id, $num_id) = $profile;
    echo $name_surname;
}
localheinz
  • 9,179
  • 2
  • 33
  • 44
Don't Panic
  • 41,125
  • 10
  • 61
  • 80
1

If I understood your question, you could try this function:

function sortValuesKeepKey($lines) {

        //declare arrays to be used temporarily
        $idNumbers = array();
        $values = array();
        $return = array();

        //loop through each line and seperate the number at the beginning
        //of the string from the values into 2 seperate arrays
        foreach($lines as $line) {
            $columns = explode("|", $line);
            $id = array_shift($columns);

            $idNumbers[] = $id;
            $values[] = implode("|", $columns);
        }

        //sort the values without the numbers at the beginning
        asort($values);

        //loop through each value and readd the number originally at the beginning 
        //of the string
        foreach($values as $key => $value) {
            //use $key here to ensure your putting the right data back together.
            $return[$key] = $idNumbers[$key]."|".$values[$key];
        }

        //return finished product
        return $return;
    }

Just pass it the lines as an array and it should return it ordered properly.

GrumpyCrouton
  • 8,486
  • 7
  • 32
  • 71
1

You can avoid the complexity of a uasort() call if you just position your columns in the order that you want to alphabetize them. This method has the added benefit of sorting all column data from left to right. This means, regardless of sorting direction (asc or desc), my method will sort $rows[0], then $row[1], then $row[2], then $row[3].

I have also logically combined your two if statements and set ASC as the default sorting direction.

Code: (Demo)

$txt=['9999|Marco|markkkk998|355647689','1|Marco|markkkk998|355647689','3692|Giovanni|giojo982|0005405','9797|Stefano|stefy734|45367','2566|Marco|markkkk998|355647689','4721|Roberto|robn88|809678741'];

foreach($txt as $row){
    $values=explode('|',$row);
    $rows[]=[$values[1],$values[0],$values[2],$values[3]];  // just reposition Name column to be first column
}
if(isset($_GET['Z-A'])) {
    arsort($rows);  // this will sort each column from Left-Right using Z-A
}else{
    asort($rows);  // (default) this will sort each column from Left-Right using A-Z
}
// var_export($rows);
foreach($rows as $i=>$profile) {
    echo "$i {$profile[0]}\n";  // name value
}

Output:

2 Giovanni
1 Marco
4 Marco
0 Marco
5 Roberto
3 Stefano
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
  • Interesting, but i'm not able to echo the name, for example... :( I need to create another foreach loop? – Devilix Aug 08 '17 at 14:07
  • @Devilix Yes, My answer is just like all of the others in that you need to loop again after sorting. I have updated my answer to display this. It may be a useless feature for your case, but my method will sort the data beyond a single column. If you have duplicate names in your list, it will order the duplicate named rows based on the next column, then the next, etc. – mickmackusa Aug 08 '17 at 22:58
0

If you want to sort the values by name_surname, see the below code

$db_friends = "db_friends.txt";
$dblines = file($db_friends);
// loop the lines
foreach($dblines as $key => $profile) {
    // explode each line with the delimiter
    list($uni_id, $name_surname, $textnum_id, $num_id) = explode("|", $profile);
    // create an array with name_surname as a key and the line as value
    $array[$name_surname] = $profile;
}
// bases on the GET paramater sort the array.
if(isset($_GET['A-Z'])) {
    ksort($array);  //sort acceding
}
if(isset($_GET['Z-A'])) {
    krsort($array);  // sort descending 
}
// loop the sorted array 
foreach($array as $key => $value) {
    echo $key; // display the name_surname.
}
Ravinder Reddy
  • 3,869
  • 1
  • 13
  • 22
  • Downvoted because this answer is not correct. It does not preserve the original indexes as desired by the OP. http://sandbox.onlinephpfunctions.com/code/69c08082864e45f4ca9fa7c08219fadb7bc596c6 – mickmackusa Aug 08 '17 at 21:16