Reputation: 3496
I have an array of paths that I would like to sort ...
Array
(
/something/foo1
/something/special/foo2
/something/foo3
/something/special/foo4
/something/foo5
/something/special/foo6
)
... so that all paths that contain /special/
end up at the end of the array like this:
Array
(
/something/foo1
/something/foo3
/something/foo5
/something/special/foo2
/something/special/foo4
/something/special/foo6
)
The original sort order of paths must remain the same (so 1,2,3,4,5,6
=> 1,3,5,2,4,6
). Is there an elegant way to do this? Can this be implemented by using the usort function?
Upvotes: 0
Views: 1033
Reputation: 3055
you can use unset
and append []
, like so
$x = array(1,2,3);
$x[] = $x[1];
unset($x[1]);
print_r($x);
Array
(
[0] => 1
[2] => 3
[3] => 2
)
You can thus loop over the array, test each element, and flip to the end the ones that contain the pattern.
$len = count($a);
for ($i=0; $i<$len; $i++) {
if (...) {
$a[] = $a[i];
unset($a[i]);
}
}
Edit: php's arrays are lists, hashes and arrays simultaneously. It is possible to move an element to the end while retaining its index! For example
$a = array(1,2,3);
$t = $a[1];
unset($a[1]);
$a[1] = $t;
print_r($a);
Array
(
[0] => 1
[2] => 3
[1] => 2
)
Upvotes: 1
Reputation: 9227
In your specific example, you can simply use asort($array);
But that is assuming foo is always foo.
Output:
array(6) {
[0]=>
string(15) "/something/foo1"
[2]=>
string(15) "/something/foo3"
[4]=>
string(15) "/something/foo5"
[1]=>
string(23) "/something/special/foo2"
[3]=>
string(23) "/something/special/foo4"
[5]=>
string(23) "/something/special/foo6"
}
If that's not the case, let me know and I'll do something else
... here is new method ref comment:
$array = array(
'/something/zoo',
'/something/special/foo',
'/something/loo',
'/something/special/goo',
'/something/boo',
'/something/special/poo'
);
uasort($array, function($a, $b) {
$specialInA = strpos($a, '/special/') !== false;
$specialInB = strpos($b, '/special/') !== false;
if ($specialInA > $specialInB) {
return 1;
}
if ($specialInB > $specialInA) {
return -1;
}
return $a > $b;
});
Output:
array(6) {
[4]=>
string(14) "/something/boo"
[2]=>
string(14) "/something/loo"
[0]=>
string(14) "/something/zoo"
[1]=>
string(22) "/something/special/foo"
[3]=>
string(22) "/something/special/goo"
[5]=>
string(22) "/something/special/poo"
}
Can probably be written better but should work
Upvotes: 2