0

I have this array:

  $routes = array(
  array(
     'code' => 'PZSA',
     'name' => 'PLaza san antonio',
  ),
  array(
     'code' => 'AVAD',
     'name' => 'Av de asturias',
  ),
  array(
     'code' => 'AVAR',
     'name' => 'Av simon nieto',
  )
  );

And I want to sort it based on the next keys:

$target = array('AVAD', 'AVAR', 'PZSA');

So the sorted array will be:

Array
(
[0] => Array
    (
        [code] => AVAD
        [name] => Av de asturias
    )

[1] => Array
    (
        [code] => AVAR
        [name] => Av simon nieto
    )

[2] => Array
    (
        [code] => PZSA
        [name] => PLaza san antonio
    )

)

I've tried this and it works, but I think is too much code for this simple thing. Any alternatives? Thanks.

  function _sort($array, $orderArray) {
      $ordered = array();
      foreach ($orderArray as $key) {
        $ordered[] = find($key, $array);
      }
      return $ordered;
   }

   function find($code, $routes) {
      foreach ($routes as $key => $value) {
         if ($routes[$key]['code'] == $code) {
            return $routes[$key];
         }
      }
   }

$sorted = _sort($routes, $target);
Marcos
  • 4,643
  • 7
  • 33
  • 60
  • 1
    there's a couple of things you could minimize e.g. `$routes[$key]['code']` could become `$value['code']` but multi dimensional array searches normally require a custom made function (or two) like this – scrowler Oct 10 '13 at 21:43
  • Can you use the code as the key for the array? Then you can simply lookup the values by key. – rc_luke Oct 10 '13 at 21:44

5 Answers5

2

Rather than doing what is essentially a linear search for each element, it might be quickest to re-index your original array by code:

// create the index
$indexed = array();
foreach($routes as $route) {
    $indexed[$route['code']] = $route;
}

// add each target to a new sorted array in order
$sorted = array();
foreach($target as $code) {
    $sorted[] = $indexed[$code];
}
George Brighton
  • 5,131
  • 9
  • 27
  • 36
2
$target_flip = array_flip($target);

usort($routes, function($a, $b) use ($target_flip){
    return ($target_flip[$a['code']] < $target_flip[$b['code']]) ? -1 : 1;
});

Demo:

Docs:

Peter
  • 16,453
  • 8
  • 51
  • 77
2

A little more generic solution where you can just set the key you wish to sort by and it should work for any multidimensional array.

//key to sort by
$sortBy = 'code';

$sorted = array();
foreach($routes as $route) {
  foreach($route as $key => $value) {
    if(!isset($sorted[$key])) {
      $sorted[$key] = array();
    }
    $sorted[$key][] = $value;
  }
}

array_multisort($sorted[$sortBy], SORT_ASC, $routes); 
print_r($routes)
Caleb Taylor
  • 177
  • 9
1

That's what array_multisort if for:

foreach ($routes as $key => $row) {
    $code[$key]  = $row['code'];
    $name[$key] = $row['name'];
}
array_multisort($code, SORT_ASC, $name, SORT_ASC, $routes);

print_r( $routes );

That way you don't even need a second array!

In fact in your case you need only to sort the codes so this will do the trick:

foreach ($routes as $key => $row) {
    $code[$key]  = $row['code'];
}

array_multisort($code, SORT_ASC, $routes);
Sébastien
  • 11,860
  • 11
  • 58
  • 78
1

Alternatively to the answers already mentioned (With the exception of Peter), you can use your logic with uasort(). You'll first have to define a comparison function (compare $a to $b), and build in logic using the values -1, 0, and 1 to decide whether the compared row should go before, after or stay the same.

// This sorts simply by alphabetic order
function reindex( $a, $b )
{
    // Here we grab the values of the 'code' keys from within the array.
    $val1 = $a['code'];
    $val2 = $b['code'];

    // Compare string alphabetically
    if( $val1 > $val2 ) {
        return 1;
    } elseif( $val1 < $val2 ) {
        return -1;
    } else {
        return 0;
    }
}

// Call it like this:
uasort( $routes, 'reindex' );

print_r( $routes );

Of course, that only works as a small example, and if you are trying to index them in alphabetical order. If you need it to sort by an exact set of keys, not in alphabetical order, well it might be a bit trickier, as it doesn't accept any other parameters.

PHP uasort() Reference

Jason
  • 1,987
  • 1
  • 14
  • 16