0

I am trying to sort an array with array_multisort() but it only seems to sort the first column. I would like it to sort by 4 columns. Here is my function.

function array_sort_by_column(&$arr, $col, $col2, $col3, $col4, $dir = SORT_DESC) {
    foreach ($arr as $key => $row) {
        $sort_col[$key] = $row[$col];
        $sort_col2[$key] = $row[$col2];
        $sort_col3[$key] = $row[$col3];
        $sort_col4[$key] = $row[$col4];
    }
    array_multisort($sort_col, $dir, $sort_col2, $dir, $sort_col3, $dir, $sort_col4, $dir, $arr);
}

The input here is a two dimensional array as $arr and then the column names I would like to sort by as $col1, $col2, $col3, and $col4.

EDIT: Sorry I meant 2 dimensional array

Sample:

$arr = array(
    0 => array(
        'group_id' => '1',
        'points' => '5',
        'rank' => '10',
        'diff' => '1'
    ),
    1 => array(
        'group_id' => '1',
        'points' => '1',
        'rank' => '2',
        'diff' => '4'
    ),
    2 => array(
        'group_id' => '2',
        'points' => '1',
        'rank' => '1',
        'diff' => '2'
    ),
    3 => array(
        'group_id' => '2',
        'points' => '9',
        'rank' => '0',
        'diff' => '-11'
    ),
);

array_sort_by_column($arr, 'group_id', 'points', 'rank', 'diff');
Uberswe
  • 1,038
  • 2
  • 16
  • 36
  • What is your test of inequality? – erisco Feb 23 '13 at 12:38
  • Do you have a sample of data that you're using? The function appears to work just fine for me :). It could be that your $arr array isn't structured correctly to function with array_multisort. – adomnom Feb 23 '13 at 12:42
  • I don't see anything in the documentation of `array_multisort` that says you can supply column names to sort by. – Barmar Feb 23 '13 at 12:42
  • 1
    Use `usort` with the comparison function in a closure that uses `$col`, `$col2`, etc. – Barmar Feb 23 '13 at 12:50
  • usort would be definitely a best and most customizable way to solve your problem. – MarcinWolny Feb 23 '13 at 14:09
  • I will take a look at usort, I have never used it before as I have never had the need, thanks! – Uberswe Feb 23 '13 at 14:44

1 Answers1

0

As Barmar indicates, you will need to use usort. You should place all the sorting functionality in one function or class method:

public function sort($a, $b) 
{
    $key = $this->sort_key;
    $asc = $this->sort_asc;

    if (gettype($a[$key]) == 'integer') {
        if ($a[$key] == $b[$key]) return 0;
        if ($asc == 'asc') {
            return ($a[$key] < $b[$key]) ? -1 : 1;
        } elseif ($asc == 'desc') {
            return ($a[$key] > $b[$key]) ? -1 : 1;
        }
    } elseif (gettype($a[$key]) == 'string') {

        $valA = preg_replace("/[^A-Za-z0-9]/", "", strtolower($a[$key]));
        $valB = preg_replace("/[^A-Za-z0-9]/", "", strtolower($b[$key]));

        if ($asc == 'asc') {
            return strcmp($valA, $valB);
        } elseif ($asc == 'desc') {
            return strcmp($valB, $valA);
        }
    }   
}

And invoke it like this:

$this->sort_key = 'group_id';
$this->sort_asc = 'asc';
usort($array, array($this, 'sort'));

You need to make sure you're in a class. The above method will also allow you to sort values which are strings and not just integers (i.e. you can re-use it in the future).

hohner
  • 11,498
  • 8
  • 49
  • 84
  • Thanks, I tried that like this $this->sort_key = $col; $this->sort_asc = 'desc'; usort($arr, array($this, 'sort')); $this->sort_key = $col2; usort($arr, array($this, 'sort')); $this->sort_key = $col3; usort($arr, array($this, 'sort')); $this->sort_key = $col4; usort($arr, array($this, 'sort')); And it sorts fine for group and points which is respectively col and col2 but then when it tries to sort rank it does not seem to work. I will have 4 arrays with the same groupid and points together and then the rank will be 1, -1, 0, 1 – Uberswe Feb 23 '13 at 18:34
  • Hows does it not work when you sort by rank? Are you passing in the right array to the usort function? – hohner Feb 23 '13 at 18:59
  • Ah I see what I am doing wrong here and I guess I failed to explain this in my question. What I want to achieve is a sort by the 4 columns where $col1 is primary for sorting, $col2 is secondary and so on. So I want to keep the sorting from the first usort and then the arrays with the same groupid should be sorted based on points. then the arrays with the same groupid and points should be sorted based on rank. – Uberswe Feb 24 '13 at 09:10
  • Ended up solving this issue with a combination of your example and the answer to a similar question http://stackoverflow.com/questions/3968551/php-sort-multidimensional-array-with-primary-secondary-keys – Uberswe Feb 24 '13 at 09:20