kishram
kishram

Reputation: 103

Sorting a associative array based on two keys

I want to sort the id field by pushing array record with null value to bottom. If id value is present, then sort the col_1 by asc.

I have a multidimensional array like this.

Array
(
  [0]=> Array
        (
          [id]=>1166
          [col_1]=>9.4
        )
  [1]=> Array
        (
          [id]=>
          [col_1]=>2.4
        )
  [2]=> Array
        (
          [id]=>1012
          [col_1]=>0.96
        )
  [3]=> Array
        (
          [id]=>1856
          [col_1]=>7.47
        )
)

I want to sort it by id as well as col_1. I tried

foreach ($arr as $key => $row) {
  $x[$key]  = $row['id'];
  $y[$key]  = $row['col_1'];
}
array_multisort($x, SORT_DESC, $y, SORT_ASC, $arr);

I got the following as my result

Array
(
  [0]=> Array
        (
          [id]=>1856
          [col_1]=>7.47
        )
  [1]=> Array
        (
          [id]=>1166
          [col_1]=>9.4
        )
  [2]=> Array
        (
          [id]=>1012,
          [col_1]=>0.96
        )
  [3]=> Array
        (
          [id]=>
          [col_1]=>2.47
        )
)

But I want the result as,

Array
(
  [0]=> Array
        (
          [id]=>1012
          [col_1]=>0.96
        )
  [1]=> Array
        (
          [id]=>1856
          [col_1]=>7.47
        )
  [2]=> Array
        (
          [id]=>1166
          [col_1]=>9.4
        )
  [3]=> Array
        (
          [id]=>
          [col_1]=>2.4
        )
)

'id' field can be null also for some records. But col_1 will be there for all the records.

Upvotes: 1

Views: 69

Answers (2)

arkascha
arkascha

Reputation: 42984

Not exactly sophisticated, but readable and straight forward:

<?php
$data = [
    [
        'id' => 1166,
        'col_1' => 9.4
    ],
    [
        'id' => null,
        'col_1' => 2.4
    ],
    [
        'id' => 1012,
        'col_1' => 0.96
    ],
    [
        'id' => 1856,
        'col_1' => 7.47
    ]
];
usort($data, function($a, $b) {
    return ($a['col_1']>$b['col_1']);
});
usort($data, function($a) {
    return !isset($a['id']);
});
print_r($data);

The output obviously is:

Array
(
    [0] => Array
        (
            [id] => 1012
            [col_1] => 0.96
        )

    [1] => Array
        (
            [id] => 1856
            [col_1] => 7.47
        )

    [2] => Array
        (
            [id] => 1166
            [col_1] => 9.4
        )

    [3] => Array
        (
            [id] =>
            [col_1] => 2.4
        )

)

In your comment below you now make an additional requirement. I doubt there is a direct way to evaluate both requirements in a straight forward sorting approach. So why not try a readable and obvious one:

<?php
$data = [
    [
        'id' => 1166,
        'col_1' => 9.4
    ],
    [
        'id' => null,
        'col_1' => 2.4
    ],
    [
        'id' => null,
        'col_1' => 0.2
    ],
    [
        'id' => 1012,
        'col_1' => 0.96
    ],
    [
        'id' => null,
        'col_1' => 12
    ],
    [
        'id' => 1856,
        'col_1' => 7.47
    ]
];
usort($data, function($a, $b) {
    return ($a['col_1']>$b['col_1']);
});
$withId = array_filter($data, function($entry) {
    return isset($entry ['id']);
});
$withoutId = array_filter($data, function($entry) {
    return !isset($entry ['id']);
});
$data = array_merge($withId, $withoutId);
print_r($data);

The output obviously is:

Array
(
    [0] => Array
        (
            [id] => 1012
            [col_1] => 0.96
        )

    [1] => Array
        (
            [id] => 1856
            [col_1] => 7.47
        )

    [2] => Array
        (
            [id] => 1166
            [col_1] => 9.4
        )

    [3] => Array
        (
            [id] =>
            [col_1] => 0.2
        )

    [4] => Array
        (
            [id] =>
            [col_1] => 2.4
        )

    [5] => Array
        (
            [id] =>
            [col_1] => 12
        )

)

Upvotes: 2

Unex
Unex

Reputation: 1757

you can use the usort function to make a custom sort.

 function customSort($a, $b) {
    if (null === $a['id'] && null === $b['id']) {
        return 0;
    }
    if (null === $a['id']) {
        return 1;
    } 
    if (null === $b['id']) {
        return -1;
    }
    return ($a['col_1'] < $b['col_1']) ? -1 : 1;
}

$array = [
    [
        'id' => 1012,
        'col_1' => 0.96
        ],
    [
        'id' => 1856,
        'col_1' => 7.47
        ],
            [
        'id' => null,
        'col_1' => 2.4
        ],
    [
        'id' => 1166,
        'col_1' => 9.4
        ],

    ];



    usort($array, 'customSort');
    print_r($array);

This returns

Array
(
    [0] => Array
        (
            [id] => 1012
            [col_1] => 0.96
        )

    [1] => Array
        (
            [id] => 1856
            [col_1] => 7.47
        )

    [2] => Array
        (
            [id] => 1166
            [col_1] => 9.4
        )

    [3] => Array
        (
            [id] => 
            [col_1] => 2.4
        )

)

Which is what you expected. Hope this helped.

Upvotes: 1

Related Questions