Php 如果某些项满足特定条件,则将其移动到数组的末尾

Php 如果某些项满足特定条件,则将其移动到数组的末尾,php,arrays,sorting,usort,Php,Arrays,Sorting,Usort,我有一个路径数组,我想排序 Array ( /something/foo1 /something/special/foo2 /something/foo3 /something/special/foo4 /something/foo5 /something/special/foo6 ) 。。。因此,所有包含/special/的路径都会在数组的末尾结束,如下所示: Array ( /something/foo1 /something

我有一个路径数组,我想排序

Array
(
    /something/foo1
    /something/special/foo2
    /something/foo3
    /something/special/foo4
    /something/foo5
    /something/special/foo6
)
。。。因此,所有包含
/special/
的路径都会在数组的末尾结束,如下所示:

Array
(
    /something/foo1
    /something/foo3
    /something/foo5
    /something/special/foo2
    /something/special/foo4
    /something/special/foo6
)

路径的原始排序顺序必须保持不变(因此
1,2,3,4,5,6
=>
1,3,5,2,4,6
)。有没有一种优雅的方法可以做到这一点?这可以通过使用usort函数来实现吗

您可以使用
unset
和append
[]
,如下所示

$x = array(1,2,3);
$x[] = $x[1];
unset($x[1]);
print_r($x);

Array
(
    [0] => 1
    [2] => 3
    [3] => 2
)
因此,您可以在数组上循环,测试每个元素,并将包含该模式的元素翻转到末尾

$len = count($a);
for ($i=0; $i<$len; $i++) {
    if (...) {
        $a[] = $a[i];
        unset($a[i]);
    }
}

在您的特定示例中,您可以简单地使用
asort($array)

但这是假设foo总是foo

输出:

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"
}
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"
}
如果不是这样,请告诉我,我会做其他事情

。。。以下是新方法ref注释:

$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;
});
输出:

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"
}
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"
}

也许可以写得更好,但应该有用

哦,我可能应该早点提到这一点。实际路径完全不同。只有
特殊部分保持不变。谢谢@rjdown,我不确定是否可以编写一个排序比较函数来分隔但保留所有具有特殊路径和不具有特殊路径的数组的原始顺序,而不是不传入数组索引或引用闭包中的未排序列表。或者包装每个项目并将索引放入包装器中。Sort将调用随机选取的两个元素的比较,正确排序两个特殊行或两个非特殊行需要知道它们的原始索引。从上面可以看出,这当然是可能的。这是
usort
uasort
之间的区别-使用用户定义的比较函数对数组进行排序并维护索引关联这并不维护索引关联,因为requestedit不是必须维护的索引关联,而是排序顺序。关联也可以通过显式分配下标来维护<代码>$t=$a[$i];未结算($a[$i])$a[$i]=$t
会将$t移到末尾,索引与之前相同。Php有非常时髦的数组。他确实使用相同的键指定了顺序。不管怎样,这似乎并没有真正做到他所要求的。。。排序在哪里?那些不是键,那些是行的代理。1==…/foo1、2==…/foo2等等。不需要任何排序,只需将“包含/special/end的所有路径”分隔开来,而不需要重新排序,因为“[t]原始排序顺序……必须保持不变”。给定一个输入(a1、s2、s3、a4、a5、s6),期望的输出是未排序但去隔行的(a1、a4、a5、s2、s3、s6),末尾是“特殊”s-E。