Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP sort array by subset

I have two arrays.

One is a larger bit of data:

Array
(
    [12] => blah
    [36] => foo
    [58] => blah
    [60] => blah
    [72] => blah
    [90] => bar
)

The other is a smaller subset of different but related data in a different order, with each key corresponding to the same key in the larger array:

Array
(
    [36] => foo data
    [90] => bar data
    [12] => blah data
)

Now, my question is, how do I get the first array to be in such an order so that the keys in the first array that have corresponding keys in the second array will appear first and in the same order as the second array?

Thus, like this:

Array
(
    [36] => foo
    [90] => bar
    [12] => blah
    [58] => blah
    [60] => blah
    [72] => blah
)
like image 902
herpyderpy Avatar asked Jun 27 '11 22:06

herpyderpy


People also ask

How does Usort work in PHP?

The usort() function in PHP sorts a given array by using a user-defined comparison function. This function is useful in case if we want to sort the array in a new manner. This function assigns new integral keys starting from zero to the elements present in the array and the old keys are lost.

What is Array_chunk function in PHP?

PHP array_chunk() Function The array_chunk() function takes an array as input and split that array into smaller chunks of the given size. The last chunk may contain less number of elements than passed size based on the multiplicity factor of the total numbers available in the array.

What are the parameters required in Array_slice?

Parameters: This function can take four parameters and are described below: $array (mandatory): This parameter refers to the original array, we want to slice. $start_point (mandatory): This parameter refers to the starting position of the array from where the slicing need to be performed.

Which of the function is used to sort an array in descending order?

rsort() - sort arrays in descending order. asort() - sort associative arrays in ascending order, according to the value.


2 Answers

Simple O(n) solution.

$arr1 = array(12 => 1, 36 => 2, 58 => 3, 60 => 4, 72 => 5);
$arr2 = array(36 => 1, 60 => 2, 12 => 1);

$result = array();

foreach($arr2 as $key => $value) {
    $result[$key] = $arr1[$key];
    unset($arr1[$key]);
}

foreach($arr1 as $key => $value) {
    $result[$key] = $arr1[$key];
}

var_dump($result);

Output:

array(5) {
  [36]=>
  int(2)
  [60]=>
  int(4)
  [12]=>
  int(1)
  [58]=>
  int(3)
  [72]=>
  int(5)
}
like image 113
Dogbert Avatar answered Oct 30 '22 15:10

Dogbert


Here's an example using uksort with closure, it should be more effective on big array i think, but i haven't done any benchmark so... difficult to really confirm w/o test.

$a = array(
    12 => 'blah'
    ,36 => 'foo'
    ,58 => 'blah'
    ,60 => 'blah'
    ,72 => 'blah'
    ,90 => 'bar'
);

$b = array(
    36 => 'foo data'
    ,90 => 'bar data'
    ,12 => 'blah data'
);

$keysPosition = array_flip(array_keys($b));
uksort($a,function($a,$b) use ($keysPosition){
    if(isset($keysPosition[$a],$keysPosition[$b])){
        return $keysPosition[$a]>$keysPosition[$b]?1:-1;
    }else if( isset($keysPosition[$a]) ){
        return -1;
    }else if( isset($keysPosition[$b]) ){
        return 1;
    }
    return 0;
});

print_r($a);

result:

Array
(
    [36] => foo
    [90] => bar
    [12] => blah
    [72] => blah
    [58] => blah
    [60] => blah
)

If you can't use closure (php <5.3) you can do something similar using a global but it's not clean at all.

like image 32
malko Avatar answered Oct 30 '22 16:10

malko