skip to Main Content

I have the following code:

$check = array('person a','person c');
$data = array('person c','person a','person d','person e');
define('check',$check);
//asort($data);

print'<pre>';print_r($data);print'</pre>';

usort($data,function($a,$b){
    return empty(check[$a]) ? 1 : $a <=> $b;
});

print'<pre>';print_r($data);print'</pre>';
exit;

What I am trying to achieve is:

person d
person e
person a
person c

What I get is

person e
person a
person d
person c

Because person a and c are in the $check array, I’m trying to sort my array based on alphabetically for those not in the $check group and then those who are. I could probably split things up a bit and am not overly familiar with the usort custom functions, but is it possible to acheive it this way?

4

Answers


  1. Try this. Firstly get all the items in the first array which aren’t in the second array:

    $data = array_diff($data, $check);
    

    Sort both arrays:

    usort($data,function($a,$b){
        return $a <=> $b;
    });
    
    usort($check,function($a,$b){
        return $a <=> $b;
    });
    

    Merge them together

    $merged = array_merge($data, $check);
    
    Login or Signup to reply.
  2. Create a "mapping" array using array_map() and in_array() to flag each $data item, then array_multisort() both the mapping array and the $data array:

    <?php
    
    $check = array('person a','person c');
    $data = array('person c','person a','person d','person e');
    
    function dmap ($itm) {
        GLOBAL $check;
        return ((int)in_array($itm, $check)+1) . $itm;
    }
    
    $mm = array_map('dmap', $data);
    array_multisort($mm, $data);
    print_r($data);
    
    exit;
    

    Outputs:

    Array
    (
        [0] => person d
        [1] => person e
        [2] => person a
        [3] => person c
    )
    

    When providing two arrays to array_multisort() the function sorts the first array, ascending by default, and applies the sorted order of the first array to the second.

    The "mapping" array simply prepends a 1 or 2 to each element of the $data array to affect the sort order moving the items not found in the $check into first sort position.

    Try it here: https://onlinephp.io/c/5ae10

    Login or Signup to reply.
  3. The most modern approach is to use array_map() with arrow syntax and check if each data value is in the check array. When sorting booleans ascending, false comes before true.

    array_multisort() is a better choice versus usort() in this case because fewer in_array() call will be made.

    Code: (Demo)

    array_multisort(
        array_map(fn($v) => in_array($v, $check), $data),
        $data
    );
    var_export($data);
    
    Login or Signup to reply.
  4. Sort by 2 criteria:

    1. if the element exists in $last it should go to the end
    2. then alphabetically

    This can be done with usort alone. Some entries were added to the data to make the test more reliable.

    $data = array('person f','person c','person g','person a','person d','person e');
    
    $last = array('person a','person c','person g');
    
    usort($data,function($a,$b) use($last){
      return in_array($a,$last) <=> in_array($b,$last)  //sort if in $last
      ?: $a <=> $b;  //sort alphabetically
    });
    
    var_export($data);
    

    Demo: https://3v4l.org/B3G8s

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search