1

I have a JSON array like this

$countries = [
        {
          "id": "1",
          "country_name": "Afghanistan",
        },
        {
          "id": "2",
          "country_name": "Albania",
        },
        {
          "id": "3",
          "country_name": "Algeria",
        },
        {
          "id": "4",
          "country_name": "American Samoa",
        }       
        ..
        ..
        ..
        {
          "id": "50",
          "country_name": "Zimbabwe",
        }
];      

The following array contains, the list of countries that I need to sort to top

$top_countries = ['United States', 'United Kingdom', 'German'];

What is the best way to sort the above array as follows

$countries = [
        {
          "id": "30",
          "country_name": "United States",
        },
        {
          "id": "31",
          "country_name": "United Kingdom",
        },
        {
          "id": "20",
          "country_name": "German",
        },
        {
          "id": "1",
          "country_name": "Afghanistan",
        },
        {
          "id": "2",
          "country_name": "Albania",
        },
        {
          "id": "3",
          "country_name": "Algeria",
        },
        {
          "id": "4",
          "country_name": "American Samoa",
        }       
        ..
        ..
        ..
        {
          "id": "50",
          "country_name": "Zimbabwe",
        }
];
2
  • 1
    json_decode() + uasort() + json_encode() Commented Nov 27, 2015 at 12:16
  • Without decode, I don't think php support to sort json, So, Decode json and convert to array, make necessary sorting operations and then again convert it to json. Commented Nov 27, 2015 at 12:19

1 Answer 1

2
// index "value" of country by name
$top = array_flip($top_countries);

usort($countries, function($a, $b) use ($top) {
    // get "value" for each country, if it is in index
    $aValue = isset($top[$a->country_name])?$top[$a->country_name]:-1;
    $bValue = isset($top[$b->country_name])?$top[$b->country_name]:-1;

    if ($aValue == $bValue) {
        // preserve "original order", assuming they were ordered by id 
        return $a->id < $b->id ? -1 : 1;
    }
    return $aValue < $bValue ? 1:-1;
});
Sign up to request clarification or add additional context in comments.

7 Comments

Great! it works! Please update your answer that need to reverse the array before flip it. :)
Also, change $a->country_name to $a['country_name']
@Asik, I reverted 1 and -1 it in the return statement of the closure. It is cheaper than reverse $top_countries
Anyway, remaining countries orders are changed. I want to keep the remaining countries list order same.
Inverting order of original array won't help. I updated the answer to maintain order for "non-top" countries.
|

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.