-1

Let us suppose I have an array like below

    $item = Array(

             [0] => Array(
                     "name" => "item1"
                     "score" => 100,
                     "category" => "A1",
                     "vote"  => 80,
               )

          [1] => Array(
                 "name" => "item2",
                 "score" => 100,
                 "category" => "A1",
                 "vote"    => 70,
           )
           [2] => Array(
                 "name" => "item3",
                 "score" => 80,
                 "category" => "A2",
                 "vote"    => 80,
           )
           [3] => Array(
                 "name" => "item4",
                 "score" => 80,
                 "category" => "A2",
                 "vote"    => 60,
           )
           [4] => Array(
                 "name" => "item5",
                 "score" => 80,
                 "category" => "A3",
                 "vote"    => 80,
           )
    )

edited input:

    Array
(
    [0] => Array
        (
            [name] => item1
            [score] => 100
            [category] => A1
            [vote] => 80
        )

    [1] => Array
        (
            [name] => item2
            [score] => 100
            [category] => A1
            [vote] => 80
        )

    [2] => Array
        (
            [name] => item5
            [score] => 80
            [category] => A3
            [vote] => 80
        )

    [3] => Array
        (
            [name] => item3
            [score] => 80
            [category] => A2
            [vote] => 80
        )

    [4] => Array
        (
            [name] => item4
            [score] => 80
            [category] => A2
            [vote] => 60
        )

)

The priority of the sort is score, category and vote consequently. The expected result is :

$item = Array(

             [0] => Array(
                     "name" => "item1"
                     "score" => 100,
                     "category" => "A1",
                     "vote"    => 80,
               )
            [1] => Array(
                 "name" => "item5",
                 "score" => 80,
                 "category" => "A3",
                 "vote"    => 80,
            )
            [2] => Array(
                 "name" => "item3",
                 "score" => 80,
                 "category" => "A2",
                 "vote"    => 80,
           )

          [3] => Array(
                 "name" => "item2",
                 "score" => 100,
                 "category" => "A1",
                 "vote"    => 70,
           )

           [4] => Array(
                 "name" => "item4",
                 "score" => 80,
                 "category" => "A2",
                 "vote"    => 60,
           )

    )

edited expected result:

   Array
    (
    [0] => Array
        (
            [name] => item1
            [score] => 100
            [category] => A1
            [vote] => 80
        )

    [1] => Array
        (
            [name] => item5
            [score] => 80
            [category] => A3
            [vote] => 80
        )

    [2] => Array
        (
            [name] => item3
            [score] => 80
            [category] => A2
            [vote] => 80
        )
   [3] => Array
        (
            [name] => item2
            [score] => 100
            [category] => A1
            [vote] => 80
        )

    [4] => Array
        (
            [name] => item4
            [score] => 80
            [category] => A2
            [vote] => 60
        )

)

I want to have the distinct categories at the top sorted based on the score and then vote but if they are two items with the same category, the item with the lower score will have lower priority.

Based on the insight from , I first sort the array based on score, category and vote

foreach($list as $k=>$v) {
        $sorted['score'][$k] = $v['score'];
        $sorted['category'][$k] = $v['category'];
        $sorted['vote'][$k] = $v['vote'];
    }

    array_multisort($sorted['score'], SORT_DESC, $sorted['category'], SORT_DESC,$sorted['vote'], SORT_DESC, $list);

It will give me:

    Array
(
    [0] => Array
        (
            [name] => item1
            [score] => 100
            [category] => A1
            [vote] => 80
        )

    [1] => Array
        (
            [name] => item2
            [score] => 100
            [category] => A1
            [vote] => 80
        )

    [2] => Array
        (
            [name] => item5
            [score] => 80
            [category] => A3
            [vote] => 80
        )



  [3] => Array
        (
            [name] => item3
            [score] => 80
            [category] => A2
            [vote] => 80
        )
    [4] => Array
        (
            [name] => item4
            [score] => 80
            [category] => A2
            [vote] => 60
        )

)

I need to re-sort the result again to have the distinct categories at the top (see the edited expected result)

Edited: It seems my example and question are confusing. The idea is I want to sort the item based on the score and then vote but the category should be taken into consideration. On top of score and vote, I want to have the time with the distinct categories on top and then the score and vote follow.

5
  • 1
    You must define a comparison function and use usort() stackoverflow.com/questions/24559050/… Commented Oct 9, 2015 at 16:39
  • I have answered a similar question and my answer was accepted, see if adapting it works for you Commented Oct 9, 2015 at 16:43
  • i'm a bit confuse, which is you priority is the score is high but the vote is low? Commented Oct 10, 2015 at 7:32
  • the score is preferable that the vote. vote is the second priority. But the category should be taken into consideration. But on top of that I want to have distinct(different) categories as the priority first then the score and vote follow as mentioned above. Commented Oct 10, 2015 at 7:38
  • okay.. i have a suggestion though, why don't you sort them by category first then have a sorting for both votes and scores? and make life a little easier? Commented Oct 10, 2015 at 9:05

2 Answers 2

1

use array_multisort()

<?php
$mylist = Array(

             0 => Array(
                     "name" => "item1",
                     "score" => 100,
                     "category" => "A1",
                     "vote"  => 80
               ),

          1 => Array(
                 "name" => "item2",
                 "score" => 100,
                 "category" => "A1",
                 "vote"    => 70
           ),
           2 => Array(
                 "name" => "item3",
                 "score" => 80,
                 "category" => "A2",
                 "vote"    => 80
           ),
           3 => Array(
                 "name" => "item4",
                 "score" => 80,
                 "category" => "A2",
                 "vote"    => 60
           ),
           4 => Array(
                 "name" => "item5",
                 "score" => 80,
                 "category" => "A3",
                 "vote"    => 80
           )
    );

$sort = array();
foreach($mylist as $k=>$v) {
    $sort['score'][$k] = $v['score'];
    $sort['category'][$k] = $v['category'];
    $sort['vote'][$k] = $v['vote'];
}
# sort by event_type desc and then title asc
array_multisort($sort['vote'], SORT_DESC,$sort['score'], SORT_DESC, $sort['category'], SORT_DESC,$mylist);
    echo '<pre>';
    print_r($mylist);
    echo '</pre>';
?>
Sign up to request clarification or add additional context in comments.

Comments

0

NOTE: This is not an answer, this is just a suggestion. suppose to be a comment but there are codes and it's quite long.

First i just revamped your input array to this model:

enter image description here

Using this code:

$compiled = array();

for ($i = 0; $i < count($input_arr); $i++)
{
    $cat = $input_arr[$i]['category'];

    $index = count($compiled[$cat]);

    $compiled[$cat][$index]['name'] = $input_arr[$i]['name'];
    $compiled[$cat][$index]['score'] = $input_arr[$i]['score'];
    $compiled[$cat][$index]['vote'] = $input_arr[$i]['vote'];
    $compiled[$cat][$index]['overall'] = $input_arr[$i]['score'] + $input_arr[$i]['vote'];
}

I just arranged it by category. And also i added overall it's just the sum of score and vote. :)

All the sorting comes here:

foreach ($compiled as $k => $v)
{
    $json['sorted_by_vote'][$k] = sort_sub_value($compiled[$k], 'vote', false);

    $json['sorted_by_score'][$k] = sort_sub_value($compiled[$k], 'score', false);

    for ($i = 0;$i < count($compiled[$k]); $i++)
    {
        $json['sorted_by_overall'][] = $compiled[$k][$i];
    }
}
$json['sorted_by_overall'] = sort_sub_value($json['sorted_by_overall'], 'overall', false);

$json['input'] = $input_arr;

$json['revamp'] = $compiled;

echo json_encode($json);

function sort_sub_value($array, $subkey, $is_asc = true)
{
    foreach($array as $k=>$v) 
    {
        $b[$k] = strtolower($v[$subkey]);
    }

    if ($is_asc)
        asort($b); // asort -> asc | arsort ->desc
    else
        arsort($b);

    foreach($b as $key=>$val) 
    {
        $c[] = $array[$key];
    }
    return $c;
}

and will produce this:

enter image description here

enter image description here

enter image description here

And lastly here's the sample input i just mess with the votes to test.

enter image description here

Hope this would be helpful for some other reason. Cheers brother! :)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.