0

I have a function that is looping over a bunch of items that each look something like this:

[
{"Target":"col-one","Value":0.261},
{"Target":"col-two","Value":0.881},
{"Target":"col-three","Value":0.571},
{"Target":"col-four","Value":0}
]

I would like to re-order each item so that instead of going in ascending order, it goes something like col-one, col-four, col-three, col-two. Is there a relatively simple method that can accomplish this type of arbitrary sorting?

To be clear, I want the result to look like the following:

[
     {"Target":"col-one","Value":0.261}, 
     {"Target":"col-four","Value":0}, 
     {"Target":"col-three","Value":0.571}, 
     {"Target":"col-two","Value":0.881}

]

3
  • Arbitrary sorting? You mean 'shuffle'? There is a function for that, which is called.. shuffle :-) Commented Apr 12, 2018 at 20:31
  • You mean like Sort an array by values using a user-defined comparison function? Commented Apr 12, 2018 at 20:36
  • Maybe that wasn't the best wording. I don't want the re-ordering to be random. I said arbitrary because I don't want it to sort alphabetical or numerically. I want to be able to explicitly state how I want the order to go. Ideally there would be some sort of method like the following: array.sortObjects('col-one', 'col-four', 'col-three', 'col-two') Commented Apr 12, 2018 at 20:37

3 Answers 3

2

If you have an array that defines the sort order, like:

$order = ['col-one', 'col-four', 'col-three', 'col-two'];

You can pass it into the usort comparison function and look up the sort index there. I think it's easier if you flip it so the text becomes the key.

$order = array_flip($order);

usort($items, function($a, $b) use ($order) {
    return $order[$a->Target] <=> $order[$b->Target];
});

If you don't flip it first, you have to array_search repeatedly instead. (Unless there's a better way I don't know of.)

usort($items, function($a, $b) use ($order) {
    return array_search($a->Target, $order) <=> array_search($b->Target, $order);
});
Sign up to request clarification or add additional context in comments.

2 Comments

Hi , I have posted one solution, I have been following your answer since few months and enjoying them too ,please correct me if I am wrong on my answer. But your solution looker neater than mine :)
Hi @sumit. Thanks! Your answer shows an interesting approach to this problem. A couple of notes about it: it produces a result with a one-to-one relationship with the custom order array, which is fine in this case, but in a more general case there might be multiple entries in the array you're sorting for each of the items in order array. Also, there's an extra array around each of the objects in the result, but that can be fixed by returning a single item from the array_filter result.
1

I think I understood your question , you want to sort your array in any order you want. You can use array_map

$json='[
{"Target":"col-one","Value":0.261},
{"Target":"col-two","Value":0.881},
{"Target":"col-three","Value":0.571},
{"Target":"col-four","Value":0}
]';

$order_to_sort=array('col-four','col-one','col-three','col-two');
$arr=json_decode($json);

function sortObjects($arr,$order_to_sort){
return array_map(function ($a)use($arr) { return array_filter($arr, function($elem) use($a){
    return $elem->Target === $a;
}); }, $order_to_sort);
}
echo "<pre>";
print_r(sortObjects($arr,$order_to_sort));

Comments

0

Two ways: sort the array using a custom callback function usort http://php.net/manual/en/function.usort.php , or write an array that's only the columns, then array_map to the new one: http://php.net/manual/en/function.array-map.php

usort

Make a new array that shows the column order you want.

$columns = ['col-four', 'col-two', 'col-three', 'col-one'];

Apply a sort function that compares the two column names by their index:

usort($targets, function ($a, $b) use ($columns) {
    return array_search($a->Target], $columns) - array_search($b->Target], $columns);
});

So we're sorting, by comparing the difference in index.

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.