4

I have one array ($sort) that looks like:

  [1]=>16701

  [2]=>16861

  [3]=>16706

And an array ($images), which looks like:

  [0]=>
  array(4) {
    ["href"]=> string(35) "mystring"
    ["url"]=>  string(67) "mystring2"
    ["didascalia"]=> string(29) "mystring3"
    ["id"]=> 16861
  }
  [1]=>
  array(4) {
    ["href"]=> string(35) "mystring"
    ["url"]=>  string(70) "mystring2"
    ["didascalia"]=> string(37) "mystring3"
    ["id"]=> 16706
  }
  [2]=>
  array(4) {
    ["href"]=> string(35) "mystring"
    ["url"]=>  string(66) "mystring2"
    ["didascalia"]=> string(24) "mystring3"
    ["id"]=> 16701
  }

I need to sort $images, based on value "id", using $sort. So my result should be

[0]=>
array(4) {
  ["href"]=> string(35) "mystring"
  ["url"]=>  string(66) "mystring2"
  ["didascalia"]=> string(24) "mystring3"
  ["id"]=> 16701
}

[1]=>
array(4) {
  ["href"]=> string(35) "mystring"
  ["url"]=>  string(67) "mystring2"
  ["didascalia"]=> string(29) "mystring3"
  ["id"]=> 16861
}

[2]=>
array(4) {
  ["href"]=> string(35) "mystring"
  ["url"]=>  string(70) "mystring2"
  ["didascalia"]=> string(37) "mystring3"
  ["id"]=> 16706
}

How can I do it? I tried using multisort, array_map but without success.

Padmanathan J
  • 4,614
  • 5
  • 37
  • 75
topoftheforts
  • 319
  • 3
  • 10

3 Answers3

9

Since you already have the ids in the desired sort order, the only barrier to sorting $images efficiently is the inability to immediately fetch an image given its id. So let's fix that by reindexing $images to use the id as the array key using array_column (don't get thrown by the name, it can also be used for reindexing):

// array_column is only available in PHP 5.5+
$images = array_column($images, null, 'id');

After this it's trivial to get a sorted array:

$sortedImages = [];
foreach ($sort as $id) {
    $sortedImages[] = $images[$id];
}

For PHP < 5.5 you can substitute the array_column reindexing with this:

$imageIds = array_map(function($i) { return $i['id']; }, $images);
$images = array_combine($imageIds, $images);

Alternatively you can get an implementation written in PHP by the author of array_column himself.

Jon
  • 428,835
  • 81
  • 738
  • 806
  • I honestly didn't understand your solution, but it works, so thanks. I only had to substitute `$sortedImages = [];` with `$sortedImages = array();` because it gave me an error. – topoftheforts Sep 05 '13 at 09:55
  • 1
    @topoftheforts: Was it the reindexing part or the loop part that was unclear? The `[]` error happened because that's the new (compact) array literal syntax introduced with PHP 5.4, while you seem to be on 5.3. – Jon Sep 05 '13 at 09:56
  • The reindexing, but I should check for the two functions you used before asking for an explanation, so don't worry, it's just my ignorance :) Ok clear about the error! Thanks – topoftheforts Sep 05 '13 at 09:59
3

Try this:

$final = array();

foreach ($sort as $key) {
   foreach ($images as $img) {
      if($img['id'] == $key) {
         $final[] = $img;
      }
   }
}

print_r($final);
Boolean_Type
  • 1,146
  • 3
  • 13
  • 40
cartina
  • 1,409
  • 13
  • 21
  • This is not a bad solution, but I was looking for something better in terms of performance. In my example there are three elements, but my real array has ~20. So this would mean ~400 iterations, too much. – topoftheforts Sep 05 '13 at 09:53
0

In PHP 7+, it's possible to sort the input array directly and in-place according to the other described by the other array using usort and an anonymous comparison function that employs the spaceship operator

<?php
$sort = [16701, 16861, 16706];
$images = ...; // input array


// Create assoc array mapping the IDs in $sort to their desired sorted position.
$idOrder = array_combine($sort, range(0, count($sort)-1));

// Sort $images in-place according to the 'id' key, using the order
// described by $idOrder.
usort($images, function ($left, $right) use ($idOrder) {
    return $idOrder[$left['id']] <=> $idOrder[$right['id']];
});
Brian61354270
  • 8,690
  • 4
  • 21
  • 43