通过排序将数组元素移动到数组末尾

3

如果我有一个这样的数组(它可以是任意数字组合):

$arr = array(1, 2, 4, 2, 3, 5, 4, 2, 1);

我希望将所有等于4的元素移动到数组的末尾,同时保留其他元素的顺序,因此我的最终数组应该是:
1, 2, 2, 3, 5, 2, 1, 4, 4

我认为可以通过使用排序函数来实现这一点:

uasort($arr, function($a, $b){
    return $b == 4 ? -1 : 1;
});

使用上述代码将“4”元素移到末尾,但破坏了其他元素的顺序,这是我的结果:

2, 3, 1, 2, 5, 2, 1, 4, 4

我的排序处理程序应该长什么样?/有比对数组进行排序更好的方法吗?

请注意:我想保留我的数组键(因此使用uasort

eval.in


你的处理程序没有考虑到 $a。只需加入一个针对 4 的子句,然后使用您用于普通排序的处理程序。将 1 替换为 ($a < $b ? -1 : 1)(当然不考虑相等情况)。 - undefined
@halfer 我本来没想到会需要这样做,因为我不想要任何“逻辑”排序。你的解决方案并没有给我想要的结果,但还是谢谢。 - undefined
1
啊对,我漏掉了那个。好吧,回调排序方法对此感觉不合适 - Rizier的方法不错! - undefined
@halfer 我不同意。我认为这是一种排序的形式,尽管不太常规。 - undefined
这是一种排序形式,但我认为你需要将所有其他比较声明为“不关心”,这可能是一种未定义的行为。嗯,不过试试把你上面的处理程序中的1换成0,看看是否保持了所有其他比较对的原样?值得一试(尽管为了可维护性/可理解性,我认为我还是会选择Rizier的方法)。 - undefined
1
@halfer 如果你有兴趣的话,我的答案使用了uasort - undefined
4个回答

4
这对你来说应该可行:
<?php

    $arr = array(1, 2, 4, 2, 3, 5, 4, 2, 1);

    foreach($arr as $k => $v) {

        if($v == 4) {
            unset($arr[$k]);
            $arr[$k] = $v;  
        }

    }

    print_r($arr);

?>

输出:

//before 
Array ( [0] => 1 [1] => 2 [2] => 4 [3] => 2 [4] => 3 [5] => 5 [6] => 4 [7] => 2 [8] => 1 ) 
//after                    ^ key ^  value                      ^ key ^ value  
Array ( [0] => 1 [1] => 2 [3] => 2 [4] => 3 [5] => 5 [7] => 2 [8] => 1 [2] => 4 [6] => 4 )
                                                                      //^     ^  ^     ^

谢谢Rizier,但这样做无法保留我的数组键。 - undefined
@George 更新了我的答案,现在应该保留键值! - undefined
谢谢Rizier,我希望有人能提供一个能满足我的需求的排序处理程序。虽然这不是最理想的选择,但也算是下一步的好办法。 - undefined

3

以下是使用 uasort 的一种方法:

$arr = array(1, 2, 4, 2, 3, 5, 4, 2, 1);

uasort($arr, function($a, $b){
    if ($a == 4) return -1;
    if ($b == 4) return 1;
    return 0;
});

$arr = array_reverse($arr, true);

print_r($arr);
array_reverse函数的true参数会保留数组中的键名。个人认为return 0是可选的,但可以提高代码的清晰度。
输出结果:
Array
(
    [0] => 1
    [3] => 2
    [1] => 2
    [4] => 3
    [5] => 5
    [7] => 2
    [8] => 1
    [2] => 4
    [6] => 4
)

一些对应同一值的键被混淆是不可避免的事实。

这正是我在寻找的,谢谢Tom。我已经将你的最后一行改为$arr = array_reverse($arr, true); - undefined
如果你在代码中加入array_values()函数重新索引,那就更好了(也许)。像这样:$arr = array_values(array_reverse($arr, true));。这样可以使代码更加简洁清晰。 - undefined
@gmo 我认为原帖作者希望保留数组中的键。如果你想重置它们,只需将 true 参数从 array_reverse 中删除即可。 - undefined

1
这个怎么样?
<?php

$arr = array(1, 2, 4, 2, 3, 5, 4, 2, 1);
$temp= array();
foreach($arr as $index => $value){
  if($value == 4) {
    array_push($temp, $value);    
    unset ($arr[$index]);
  }
}
$result = array_merge($arr, $temp);
var_dump($result);

给我这个:
array(9) {[0]=>int(1) [1]=>int(2) [2]=>int(2) [3]=>int(3) [4]=>int(5) [5]=>int(2) [6]=>int(1) [7]=>int(4)   [8]=>int(4) }

谢谢Tramp,但是考虑到Riziers的答案,这似乎有点过头了。 - undefined
是的...我知道...我同意...在提交之后看到了...在unset中遇到了语法错误...我应该说“很棒”的工作@Riziers... - undefined

0

尝试使用...

  1. count(array_keys())
  2. array_diff()
  3. array_values()
  4. array_fill()
  5. array_merge()

示例:https://eval.in/295552

代码

<?php

// initial array
$arr = array(1, 2, 4, 2, 3, 5, 4, 2, 1);

// key to move (as a new array for array_diff)
$key_removed = array(4);

// count the number of repetitions (for array_fill)
$key_repetitions = count(array_keys($arr, $key_removed[0], true));

// new temp_array without the removed key
$temp_arr1 = array_diff($arr, $key_removed);

// reorder array index
$temp_arr1 = array_values($temp_arr1);

// add to temp_array the removed key `key_repetitions` number of times
$temp_arr2 = array_fill(count($temp_arr1) + 1, $key_repetitions, $key_removed[0]);

// merge both
$arr = array_merge($temp_arr1, $temp_arr2);

var_dump($arr);

谢谢gmo,但这并没有得到期望的结果。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接