Search code examples
phparrayssortingmultidimensional-arraycustom-sort

Sort items in a multidimensional array by the best ranking item in a column's subarray using an array of ranked values


Sort should be based on values in field [position] A person can have multiple positions (see the special case listed below).

Array
(
    [0] => Array
    (
        [position] => Array
            (
                [0] => Secretary
            )
    )
)

I want the array to be ordered on position values as

  1. General Secretary
  2. President
  3. Treasurer
  4. Secretary
  5. Committee Member

Special case for the below array, it should be the first array. Because this person is "General Secretary"

[2] => Array
(
    [person_id] => 51136
    [position] => Array
        (
            [0] => General Secretary
            [1] => Committee Member
        )

    [person_name] => Person 1
)

Example input data

Array
(
    [0] => Array
    (
        [person_id] => 22180
        [position] => Array
            (
                [0] => Secretary
            )
        [person_name] => Person 1
    )
    
    [1] => Array
    (
        [person_id] => 51135
        [position] => Array
            (
                [0] => President
            )
        [person_name] => Person 2
    )
    
    [2] => Array
    (
        [person_id] => 51136
        [position] => Array
            (
                [0] => General Secretary
                [1] => Committee Member
            )

        [person_name] => Person 3
    )
    
    [3] => Array
    (
        [person_id] => 44141
        [position] => Array
            (
                [0] => Treasurer 
            )

        [person_name] => Person 4
    )
    
    [4] => Array
    (
        [person_id] => 51137
        [position] => Array
            (
                [0] => Committee Member
            )
        [person_name] => Person 5
    )
)

Output required

Array
(
    [0] => Array
    (
        [person_id] => 51136
        [position] => Array
            (
                [0] => General Secretary
                [1] => Committee Member
            )

        [person_name] => Person 3
    )
    [1] => Array
    (
        [person_id] => 51135
        [position] => Array
            (
                [0] => President
            )
        [person_name] => Person 2
    )
    [2] => Array
    (
        [person_id] => 44141
        [position] => Array
            (
                [0] => Treasurer 
            )

        [person_name] => Person 4
    )
    [3] => Array
    (
        [person_id] => 22180
        [position] => Array
            (
                [0] => Secretary
            )
        [person_name] => Person 1
    )
    [4] => Array
    (
        [person_id] => 51137
        [position] => Array
            (
                [0] => Committee Member
            )
        [person_name] => Person 5
    )
)

Solution

  • Alright, I make this out.

    You can still use usort() instead of re-inventing the wheel. Just compare two person by the position like array_search($position,$pos_array).

    function sortByPosition($ps)
    {
        $pos=array(0=>"General Secretary",1=>"President",2=>"Treasurer",3=>"Secretary",4=>"Committee Member");
        usort($ps,function($p1,$p2) use ($pos){
            $lvl1=count($pos);
            $lvl2=count($pos);
            foreach($p1["position"] as $position)
            {
                $lvl1=min(array_search($position,$pos),$lvl1);
            }
            foreach($p2["position"] as $position)
            {
                $lvl2=min(array_search($position,$pos),$lvl2);
            }
            return $lvl1-$lvl2;
        });
        return $ps;
    }
    

    Test:

    $arr=Array(Array("person_id" => 22180,"position" => Array("Secretary"),"person_name" => "Person 1"), Array("person_id" => 51135,"position" => Array("President"),"person_name" => "Person 2"), Array("person_id" => 51136,"position" => Array("General Secretary","Committee Member"),"person_name" => "Person 3"), Array("person_id" => 44141,"position" => Array("Treasurer"),"person_name" => "Person 4"), Array("person_id" => 51137,"position" => Array("Committee Member"),"person_name" => "Person 5"));
    print_r(sortByPosition($arr));
    

    Outputs:

    Array
    (
        [0] => Array
            (
                [person_id] => 51136
                [position] => Array
                    (
                        [0] => General Secretary
                        [1] => Committee Member
                    )
    
                [person_name] => Person 3
            )
    
        [1] => Array
            (
                [person_id] => 51135
                [position] => Array
                    (
                        [0] => President
                    )
    
                [person_name] => Person 2
            )
    
        [2] => Array
            (
                [person_id] => 44141
                [position] => Array
                    (
                        [0] => Treasurer
                    )
    
                [person_name] => Person 4
            )
    
        [3] => Array
            (
                [person_id] => 22180
                [position] => Array
                    (
                        [0] => Secretary
                    )
    
                [person_name] => Person 1
            )
    
        [4] => Array
            (
                [person_id] => 51137
                [position] => Array
                    (
                        [0] => Committee Member
                    )
    
                [person_name] => Person 5
            )
    
    )