0

The sorting of array in alphabetical order is not outputting correctly.

It outputted as:

Demo
qwerty
Demo3
Test1
Test2
New1

Instead of:

Demo
Demo3
New1
qwerty
Test1
Test2

Code:

$dbresults = array(
    "0" => array (
        "id" => "1",
        "cb_boutiquename1" => "Test1",
        "cb_boutiquename2" => "Test2",
        "cb_boutiquename3" => "New1"
    ),
    "1" => array (
        "id" => "2",
        "cb_boutiquename1" => "Demo",
        "cb_boutiquename2" => "qwerty",
        "cb_boutiquename3" => "Demo3"
    )
);
           
function sortarray($a, $b) {
    return strcmp($a["cb_boutiquename$i"], $b["cb_boutiquename$i"]);
    }

    usort($dbresults, "sortarray");

    while (list($key, $value) = each($dbresults)) {
        $results[] = $value ;
    }
    
    foreach($results as $result) {
        $i = 1;
        while (array_key_exists("cb_boutiquename$i", $result)) {
        if ($result["cb_boutiquename$i"] !='') {
            echo '<a href=' . cbSef( 'index.php?option=com_comprofiler&task=page&user=' . (int) $result['id'] . '&b=' . $i . getCBprofileItemid( false )) . '>' . $result["cb_boutiquename$i"] . '</a><br />';
        }
        ++$i;
    }
}
4

3 Answers 3

1

Your problem is that in here:

function sortarray($a, $b) {
    return strcmp($a["cb_boutiquename$i"], $b["cb_boutiquename$i"]);
}

$i is undefined so you are basically comparing one undefined array offset with another.

If you want to specify which of the cb_boutiquename fields to specify at runtime then what you probably want to do is include the $i in the function, on php this can be done with a function that returns a closure (PHP 5.3+).

function getSorter($idx){
       return function($a, $b) use ($idx) {
           return strcmp($a["cb_boutiquename$idx"], $b["cb_boutiquename$idx"]);
       };
}

This returns a function that closes over the supplied argument and is appropriate for use as a comparison function for usort. So for your sort call you would use:

usort($dbresults, getSorter(1));

Or for a more general solution that does not assume the cb_boutiquename prefix on the properties you can change this to

function getSorter($idx){
       return function($a, $b) use ($idx) {
           return strcmp($a[$idx], $b[$idx]);
       };
}
usort($dbresults, getSorter("cb_boutiquename1"));

This will allow you to sort any array of arrays by an one of the indexes.

UPDATE I completely misunderstood the goal of this exercise. What you want to do is to flatten your array prior to doing any sorting.

    $dbresults= array ( "0"  => array ( "id" => "1",
                          "cb_boutiquename1" => "Test1",
                          "cb_boutiquename2" => "Test2",
                          "cb_boutiquename3" => "New1"
                             ),
          "1" => array ( "id" => "2",
                          "cb_boutiquename1" => "Demo",
                          "cb_boutiquename2" => "qwerty",
                          "cb_boutiquename3" => "Demo3"
                             )
        );

// flatten out the array
$results = array();
foreach($dbresults as $k=>$v){
    foreach ($v as $key=>$value) {
          if (substr($key, 0,15) == "cb_boutiquename"){
              $results[] = array("id"=>$v["id"], "cb_boutiquename"=>$value, "i"=>substr($key, 15));
          }
    }

}

usort($results, function($a, $b){ return strcasecmp($a["cb_boutiquename"], $b["cb_boutiquename"]); });
foreach($results as $result){
    echo '<a href=' . cbSef( 'index.php?option=com_comprofiler&task=page&user=' . (int) $result['id'] . '&b=' . $result["i"] . getCBprofileItemid( false )). '>' . $result["cb_boutiquename"] . '</a><br />'."\n";
}
Sign up to request clarification or add additional context in comments.

6 Comments

@Greystoke are you using php 5.3 or greater?
@Graystoke sorry... I realized I forgot the semicolon after the return statement, updated the answer to reflect this.
It is now outputting: Demo qwerty Demo3 Test1 Test2 New1
I misunderstood your question entirely...you need to flatten the array prior to doing any sorting. I will post a solution.
Thank you. cb_boutiquename goes up to cb_boutiquename30 in the array. Do I need to add a line for each of the cb_boutiquename. Like: $results[] = array("id"=>$v["id"], "cb_boutiquename"=>$v["cb_boutiquename30"], "i"=>3);
|
0

Instead of your sortarray function, use simply this:

asort($dbresults);

No need to reinvent the wheel. Read about it here

2 Comments

I replaced usort($dbresults, "sortarray"); with asort($dbresults); but it didn't sort them correctly. It gave: Test1 Test2 New1 Demo qwerty Demo3
Yeah, but the idea was to change your whole sortarray function with asort($dbresults);... there is no need to build a new function to do something that PHP already does for itself... In the documentation link I placed on the answer you have a few examples explaining how to use it.
0

You will need to consolidate the values from the multiple subarrays before sorting them. When sorting, add parameters to inform the algorithm to sort the strings case-insensitively. Demo

$names = [];
foreach ($dbresults as $row) {
    array_push(
        $names,
        $row['cb_boutiquename1'],
        $row['cb_boutiquename2'],
        $row['cb_boutiquename3']
    );
}
sort($names, SORT_STRING | SORT_FLAG_CASE);
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.