Sorting a PHP Array of Arrays by Custom Order

Sorting a php array of arrays by custom order

You can use usort() to dictate precisely how the array is to be sorted. In this case, the $order array can be used within the comparison function.

The example below uses a closure to make life easier.

$order = array(3452342, 5867867, 7867867, 1231233);
$array = array(
array('id' => 7867867, 'title' => 'Some Title'),
array('id' => 3452342, 'title' => 'Some Title'),
array('id' => 1231233, 'title' => 'Some Title'),
array('id' => 5867867, 'title' => 'Some Title'),
);

usort($array, function ($a, $b) use ($order) {
$pos_a = array_search($a['id'], $order);
$pos_b = array_search($b['id'], $order);
return $pos_a - $pos_b;
});

var_dump($array);

The key to this working is having the values that are being compared, be the positions of the ids within the $order array.

The comparison function works by finding the positions of the ids of two items to be compared within the $order array. If $a['id'] comes before $b['id'] in the $order array, then the return value of the function will be negative ($a is less so "floats" to the top). If $a['id'] comes after $b['id'] then the function returns a positive number ($a is greater so "sinks" down).

Finally, there is no special reason for using a closure; it's just my go-to way of writing these sorts of throwaway functions quickly. It could equally use a normal, named function.

PHP sort multidimensional array with custom order

Your usort is not working because $a and $b in the callback function are not quite what you think they are. They aren't 'term_id' values. They are the entire inner array, e.g.

array('term_id' => 76, 'content' => 'ratio')

So using them as an argument to array_search with your $order array won't work, because they aren't in that array. All the array_searches will just return false, hence the seemingly random sort. You just need to specify the term_id key, like this, and it will work as expected:

usort($attribute_content, function ($a, $b) use ($order) {
$pos_a = array_search($a['term_id'], $order);
$pos_b = array_search($b['term_id'], $order);
return $pos_a - $pos_b;
});

As far as the second way you tried, I'm really not sure what would be the problem. It appears to work properly: https://3v4l.org/oJhJs

Sort array of arrays by a column with custom sorting priority (not alphabetically)

Using Jonathan suggestion on using usort, you can define your custom rules for sorting in a separate function, like:

function getAnimalValue($animal) {
switch($animal) {
case 'Lion':
return 1;
case 'Dog':
return 2;
case 'Zeebra':
return 3;
case 'Cat':
return 4;
}
return 0;
}

Then, implement your own compare function:

function compare($itemA, $itemB) {
$a = getAnimalValue($itemA['animal']);
$b = getAnimalValue($itemB['animal']);
if ($a == $b) {
return 0;
}
return ($a < $b) ? -1 : 1;
}

Finally, call usort using the compare function:

usort($array, "compare");

php sort multidimentional array by custom order

Take the standard code for sorting an array by id:

usort($data, function($x, $y) { return $x['id'] - $y['id']; });

What you want to do is sort not by the ids themselves, but rather by the "weight" of each id (which represents the arbitrary order you want the ids to be put in). So make an array where keys are ids and values are the weights and use it to convert ids to weights:

// array_flip turns 0 => 112, 1 => 111, ... into 122 => 0, 111 => 1, ...
$weights = array_flip(array('112','111','132','100'));

usort($data, function($x, $y) use($weights) {
return $weights[$x['id']] - $weights[$y['id']];
});

Update: Since you also want to handle ids that do not have a specified weight you will have to further expand the above:

usort($data, function($x, $y) use($weights) {
if (!isset($weights[$x['id']], $weights[$y['id']])) {
// none of the ids have weight, so sort by bare id
return $x['id'] - $y['id'];
}
else if (!isset($weights[$x['id']])) {
// x does not have weight, put it last
return 1;
}
else if (!isset($weights[$y['id']])) {
// y does not have weight, put it last
return -1;
}

// both have weights, use them
return $weights[$x['id']] - $weights[$y['id']];
});

php - sort array by custom criteria

The idea is to add a priority as integer, and sort the array from the highest integer to the lowest using usort()

for example you have this data

 <?php

$data = [];

$data[0] = new stdClass;
$data[0]->name = "name1";
$data[0]->key = 'key1';

$data[1] = new stdClass;
$data[1]->name = "name2";
$data[1]->key = 'key2';

$data[2] = new stdClass;
$data[2]->name = "name3";
$data[2]->key = 'key3';


$keys = ["key3", "key1"];

you can sort it this way

function sortByPriority($data , $keys){
$priority = array();
$i = count($keys);
foreach ($keys as $key => $value) {
$i--;
$priority[$value] = $i;
}
usort($data, function($a, $b) use($priority){
$a = isset($priority[$a->key]) ? $priority[$a->key] : -1;
$b = isset($priority[$b->key]) ? $priority[$b->key] : -1;
return $b - $a;
});

return $data;
}


var_dump(sortByPriority($data, $keys));

sample output

array (size=3)
0 =>
object(stdClass)[3]
public 'name' => string 'name3' (length=5)
public 'key' => string 'key3' (length=4)
1 =>
object(stdClass)[1]
public 'name' => string 'name1' (length=5)
public 'key' => string 'key1' (length=4)
2 =>
object(stdClass)[2]
public 'name' => string 'name2' (length=5)
public 'key' => string 'key2' (length=4)

Sort array by keys in custom order

You could use the following comparison function:

function cmp($a, $b) {
$order = Array( 'LOW' => 0, 'MEDIUM' => 1, 'HIGH' => 2 );
return $order[$a] - $order[$b];
}

Example of this code is here.

Sort array in custom order using PHP

I would use the array containing all values in the correct order, and then filter out the elements which are not in the $data array:

$sortOrder = [ 'diamond', 'platinum', 'gold', 'silver', 'bronze', 'standard', 'branding' ];

$data = [ 'platinum', 'gold', 'silver', 'bronze', 'standard', 'branding', 'diamond' ];
$result = array_filter($sortOrder, fn($value) => in_array($value, $data));

Custom sort array in PHP

Here's some rough code to get you started:

Basically, it looks at the first letter of each word in the data array, the checks its position in the $sortOrder array. Letters that aren't in $sortOrder get put onto the end in the order appear.

Right off the bat, this is going to break if $sortOrder has more than 100,000 items in it. There are probably other holes too but I figure it's a decent enough example of how usort() works.

<?php
function getSortOrder($c) {
$sortOrder = array("j","c","z","l","a");
$pos = array_search($c, $sortOrder);

return $pos !== false ? $pos : 99999;
}

function mysort($a, $b) {
if( getSortOrder($a[0]) < getSortOrder($b[0]) ) {
return -1;
}elseif( getSortOrder($a[0]) == getSortOrder($b[0]) ) {
return 0;
}else {
return 1;
}
}

$data = array(
"banana",
"apple",
"love",
"zasca",
"japanese",
"car"
);

echo '<pre>' . print_r($data,true) . '</pre>';
usort($data, "mysort");
echo '<pre>' . print_r($data,true) . '</pre>';
?>


Related Topics



Leave a reply



Submit