简体   繁体   中英

sort multidimensional array twice

I have sorted a multidimensional array on value distance from low to high. This is an example of the output: (the actual output has around 20 or 30 arrays).

Array (

[0] => Array
    (
        [id] => 1
        [distance] => 5
        [sponsor] => 0
    )

[1] => Array
    (
        [id] => 20
        [distance] => 8
        [sponsor] => 1 
    )

[2] => Array
    (
        [id] => 25
        [distance] => 10
        [sponsor] => 0 
    )

[3] => Array
    (
        [id] => 78
        [distance] => 25
        [sponsor] => 1 
    )

)

After sorting on distance from low to high, I want to give priority if sponsor = 1. This is the preferred output:

Array (

[0] => Array
    (
        [id] => 20
        [distance] => 8
        [sponsor] => 1
    )

[1] => Array
    (
        [id] => 78
        [distance] => 25
        [sponsor] => 1 
    )

[2] => Array
    (
        [id] => 1
        [distance] => 5
        [sponsor] => 0 
    )

[3] => Array
    (
        [id] => 25
        [distance] => 10
        [sponsor] => 0 
    )

)

Sponsor is either 0 or 1. How can I tackle this problem? I was thinking of, before sorting on distance, I should split up the array in 2 arrays based on sponsor (0,1), sort both arrays on distance, and then merge them with sponsor=1 at the top of the new multidimensional array. Is this the way to do it?

Thank you for your input.

This is slightly modified version of what usort suggests. Assuming source array is called $arr:

usort(
  $arr, function($a, $b) {
     if ( $a['sponsor'] == $b['sponsor'] ) {
        if ( $a['distance'] == $b['distance'] ) {
            return 0;
        }
        return $a['distance'] < $b['distance'] ? -1 : 1;
     }
     return $a['sponsor'] > $b['sponsor'] ? -1 : 1;
  }
);

You have to split original array to 2 arrays: 1st has sponsor=1 , 2nd has sponsor=0 . Then sort them separately and merge.

Somehow like this:

$array1 = array_filter($array, function ($v) { return $v['sponsor'] == 1; });
$array2 = array_filter($array, function ($v) { return $v['sponsor'] == 0; });

function cmp($a, $b) {
    return $a['distance'] < $b['distance']? -1 : 1;
}

usort($array1, cmp);
usort($array2, cmp);
$result = array_merge($array1, $array2);

那会行得通,但是如果您使用稳定的排序算法,则可以先按距离排序,然后按赞助商降序排序,您将获得所需的结果。

You can use array_multisort() function to achieve what you want:

<?php

$arr = [
    ['id' => 1, 'distance' => 5, 'sponsor' => 0],
    ['id' => 20, 'distance' => 8, 'sponsor' => 1],
    ['id' => 25, 'distance' => 10, 'sponsor' => 0],
    ['id' => 78, 'distance' => 25, 'sponsor' => 1],
];

$sponsor = array_column($arr, 'sponsor');
$distance  = array_column($arr, 'distance');

// rearrange $arr by sponsor DESC and then by distance ASC
array_multisort($sponsor, SORT_DESC, $distance, SORT_ASC, $arr);

print_r($arr);

Try This :

  <?php
   $ar = array(
   array("10", 11, 100, 100, "a"),
   array(   1,  2, "2",   3,   1)
   );
   array_multisort($ar[0], SORT_ASC, SORT_STRING,
   $ar[1], SORT_NUMERIC, SORT_DESC);
   var_dump($ar);
   ?> 

or

  <?php
  $ar1 = array(10, 100, 100, 0);
  $ar2 = array(1, 3, 2, 4);
  array_multisort($ar1, $ar2);
  var_dump($ar1);
  var_dump($ar2);
  ?>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM