0

How do I sort a multidimensional array by a value, but with a custom order?

The multidimensional array will be something like:

$attribute_content[0]['term_id'] = 76; 
$attribute_content[0]['content'] = "ratio";
$attribute_content[1]['term_id'] = 18;
$attribute_content[1]['content'] = "ideal condition";
$attribute_content[2]['term_id'] = 164;
$attribute_content[2]['content'] = "genotype";
$attribute_content[3]['term_id'] = 218;
$attribute_content[3]['content'] = "genetics";
$attribute_content[4]['term_id'] = 60;
$attribute_content[4]['content'] = "height";

and the ordering is according to the term_id, but will be:

$order = array(18,164,218,60,76);

I've tried the following codes which re-order the array, but seemingly randomly:

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

and

$weights = array_flip($order);
usort($attribute_content, function($x, $y) use($weights) {
    return $weights[$x['term_id']] - $weights[$y['term_id']];
});

Please help

F Marie
  • 3
  • 2
  • 1
    Possible duplicate of [How can I sort arrays and data in PHP?](http://stackoverflow.com/questions/17364127/how-can-i-sort-arrays-and-data-in-php) – Matt S Jul 18 '16 at 21:09
  • 1
    `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; });` – splash58 Jul 18 '16 at 21:09

4 Answers4

1

Yet another approach, just add the order to the array and use that to sort:

$order = array(18, 164, 218, 60, 76);

foreach ($attribute_content as $key => $values) {
    $attribute_content[$key]['order'] = array_search($values['term_id'], $order);
}

usort($attribute_content, function($a, $b) {
    return $a['order'] > $b['order'];
});
rjdown
  • 8,530
  • 3
  • 23
  • 39
0

This is what I'd do:

$sortedArray = array();

for ($count = 0; $count < count($order); $count++) {
    for ($i = 0; $i < count($attribute_content); $i++) {
        if ($order[$count] == $attribute_content[$i]["term_id"]) {
            $sortedArray[count($sortedArray)] = $attribute_content[$i];
        }
    }
}

$attribute_content = $sortedArray;

It'll cycle through the array and put the values into a new, sorted array in the order provided. Afterwards, it will set the pre-existing array to the sorted array, however you can remove that line if you don't mind using $sortedArray, or if you just want to rename it and use it.

VortixDev
  • 832
  • 8
  • 18
0

Here's another approach using array_multisort():

<?php
$order = array(18,164,218,60,76);

$attribute_content = array(
    array('term_id' => 76, 'content' => 'ratio'),
    array('term_id' => 18, 'content' => 'ideal condition'),
    array('term_id' => 164,'content' => 'genotype'),
    array('term_id' => 218,'content' => 'genetics'),
    array('term_id' => 60, 'content' => 'height')
);

foreach($attribute_content as $k=>$r){
    $term_id = $r['term_id'];
    $custom_order = 0;

    if( in_array($term_id,$order) ){
        $custom_order = array_search($term_id,$order);
    }

    $tmp[] = $custom_order;
}

array_multisort($tmp,SORT_ASC,$attribute_content);

echo '<pre>',print_r($attribute_content),'</pre>';
Samuel Cook
  • 15,511
  • 6
  • 43
  • 58
0

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

Don't Panic
  • 37,589
  • 9
  • 55
  • 71
  • Thanks!! adding the term_id worked. I think the other didn't work because I was drawing the wrong data from another object. – F Marie Jul 18 '16 at 22:27
  • Great! Did you ever figure out what was going wrong with the other method? Just curious. – Don't Panic Jul 18 '16 at 22:28