如何在分区中反转PHP数组

时间:2016-09-26 14:10:56

标签: php arrays

我有一个看起来像这样的简单数组:

Array (
    [0] => Array (
        [id] => 8692
        [name] => d
    )
    [1] => Array (
        [id] => 8691
        [name] => c
    )
    [2] => Array (
        [id] => 8690
        [name] => b
    )
    [3] => Array (
        [id] => 8689
        [name] => a
    )
    [4] => Array (
        [id] => 8500
        [name] => d
    )
    [5] => Array (
        [id] => 8499
        [name] => c
    )
    [6] => Array (
        [id] => 8498
        [name] => b
    )
    [7] => Array (
        [id] => 8497
        [name] => a
    )
)

这个数组很长,所以我只包含前4个项目给你一个想法。

我的问题是我需要数组格式为

a,b,c,d,a,b,c,d

目前格式如下:

d,c,b,a,d,c,b,a

我的意思是['name']值,它是a,b,c或d。

所以我需要反转数组中的每4个项目。

我试图实现这一目标,但每次都以失败告终。而循环。

4 个答案:

答案 0 :(得分:7)

您可以使用array_chunkarray_mergearray_reverse执行此操作:

$finalArray = array();

$arrays = array_chunk($myArray, 4);

foreach ($arrays as $array) {
    $finalArray = array_merge($finalArray, array_reverse($array));
}

答案 1 :(得分:3)

这里的所有答案虽然完全有效,但几乎都是O(n^2)的顺序。所以我想我会给你一个O(n / 2)时间复杂度的解决方案作为替代,以防万一你关心性能。该解决方案还仅使用O(n + n + k)空间复杂度(就地交换)。

由于要求是反转值的顺序,我忽略了密钥并将解决方案基于数组始终为0索引的约束。

要解决这个问题,我们可以将解决方案概括为一个简单的数组反转,这需要使用就地交换进行简单的O(n/2)操作。我们可以使用两个计数器简单地实现这一点,从数组的开头开始$i,从数组的末尾开始$j。因此,我们可以将$arr[$i]处的值与$arr[$j]处的值进行交换,然后在每一步中递增$i并递减$j

function reverseArray(Array $arr) {
    for($i = 0, $j = count($arr); $i < $j; $i++, $j--) {
        $tmp = $arr[$j];
        $arr[$j] = $arr[$i];
        $arr[$i] = $tmp;
    }
    return $arr;
}

现在,要应用更多特定的解决方案,只反转数组中每个4个元素的组,我们只需在4个值的分区中拆分数组,并且只在每个分区处反转一时间通过将reverseArray()$i计数器的起始位置和结束位置更改为仅在每个分区内反转,仅扩展$j上面的示例。

因此,我们通过为分区大小添加另一个循环来到达O(n / 2)解决方案,并保留内部循环与前面的示例。

function reverseArrayPartition(Array $arr, $partitionSize = 4) {

    $end = count($arr);

    // reverse only one partition at a time
    for($start = 0; $start < $end; $start += $partitionSize ) {

        $from = $start;
        $to   = $start + $partitionSize - 1;

        for($i = $from, $j = $to; $i < $j; $i++, $j--) {
            // swap the transposing values
            $tmp     = $arr[$j];
            $arr[$j] = $arr[$i];
            $arr[$i] = $tmp;
        }

    }

    return $arr;

}

$arr = [4,3,2,1,4,3,2,1];
var_dump(reverseArrayPartition($arr)); // expected [1,2,3,4,1,2,3,4]

这适用于任何$partitionSize的任何数组大小,因此如果您尝试在非常大的数组上执行此操作,效率会很高。

答案 2 :(得分:2)

您可以使用for迭代数组并每次增加4并将当前偏移保持在其他变量中并使用array_slice来获取当前的数组切片并使用{{1 }}

我在考虑这样的事情:

array_reverse

for中的所有内容都可以简化为:

$step = 4;
$offset = 0;
$new_arr = []; //Here we create the new array.
for($i=0; $i<count($arr); $i+=$step) {
   $part_of_array = array_slice($arr, $offset, $step);
   $part_reverse = array_reverse($part_of_array);
   $new_arr = array_merge($new_arr, $part_reverse);
   $offset += $step;
}
print_r($new_arr); //Here will be the array as you expected.

答案 3 :(得分:-1)

不是每4次攻击,基于name

的字符代码反转
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
/**
*/
$in = [
     ['name'=>'d','id'=>1]
   , ['name'=>'c','id'=>12]
   , ['name'=>'b','id'=>13]
   , ['name'=>'a','id'=>14]
   , ['name'=>'d','id'=>15]
   , ['name'=>'c','id'=>16]
   , ['name'=>'b','id'=>17]
   , ['name'=>'a','id'=>18]
];

$last = PHP_INT_MAX;
$toReverse = [];
$out = [];
foreach ($in as $value) {
    $p = ord($value['name']);
    if ( $p < $last ) {
        //echo 'ToReverse',var_export($value,true),"\n";
        $toReverse[] = $value;
    }
    else {
        $out = array_merge($out,array_reverse($toReverse));
        //echo 'Join',var_export($out,true),"\n";
        $toReverse = [$value];

    }
    $last = $p;
}
$out = array_merge($out,array_reverse($toReverse));
print_r($out);