【问题标题】:Split an Array into N Arrays - PHP将一个数组拆分为 N 个数组 - PHP
【发布时间】:2013-03-12 20:41:28
【问题描述】:

我有一个包含 18 个值的数组:

$array = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r');

我想把这个数组分成 12 个不同的数组,所以它应该是这样的:

array(
    0 => array('a', 'b'),
    1 => array('c', 'd'),
    2 => array('e', 'f'),
    3 => array('g', 'h'),
    4 => array('i', 'j'),
    5 => array('k', 'l'),
    6 => array('m'),
    7 => array('n'),
    8 => array('o'),
    9 => array('p'),
   10 => array('q'),
   11 => array('r')
)

我的功能似乎不起作用

function array_split($array, $parts){
    return array_chunk($array, ceil(count($array) / $parts));
}

$result = array_split($array, 12);

因为我得到 9 个不同的数组而不是 12 个。它会返回

array(
    0 => array('a', 'b'),
    1 => array('c', 'd'),
    2 => array('e', 'f'),
    3 => array('g', 'h'),
    4 => array('i', 'j'),
    5 => array('k', 'l'),
    6 => array('m', 'n'),
    7 => array('o', 'p'),
    8 => array('q', 'r')
)

我该怎么做呢?谢谢。

【问题讨论】:

  • 你到底想完成什么?
  • @ExplosionPills 我想将一个包含 13 个值的数组拆分为 12 个不同的数组。这就像使用 array_chunk 函数,它根据每个数组的值来拆分数组。
  • 您没有很好地解释您的要求。或者,实际上。
  • 我的意思是类似于Management requested that I get a list of countries, but the first two countries in our DB should be considered the same and need to be grouped together
  • @ExplosionPills 好的,我在数据库中有 13 个类别,我想将它们分组为 12 个数组。如果有超过 12 个类别,则从第一个数组开始插入剩余的值。

标签: php arrays multidimensional-array split


【解决方案1】:

这个简单的功能会为你工作:

用法

$array = range("a", "r"); // same as your array
print_r(alternate_chunck($array,12));

输出

Array
(
    [0] => Array
        (
            [0] => a
            [1] => b
        )

    [1] => Array
        (
            [0] => c
            [1] => d
        )

    [2] => Array
        (
            [0] => e
            [1] => f
        )

    [3] => Array
        (
            [0] => g
            [1] => h
        )

    [4] => Array
        (
            [0] => i
            [1] => j
        )

    [5] => Array
        (
            [0] => k
            [1] => l
        )

    [6] => Array
        (
            [0] => m
        )

    [7] => Array
        (
            [0] => n
        )

    [8] => Array
        (
            [0] => o
        )

    [9] => Array
        (
            [0] => p
        )

    [10] => Array
        (
            [0] => q
        )

    [11] => Array
        (
            [0] => r
        )

)

更新以上对于大多数情况可能没有用...这是另一种类型的块

$array = range("a", "r"); // same as your array
print_r(fill_chunck($array, 5));

输出

Array
(
    [0] => Array
        (
            [0] => a
            [1] => b
            [2] => c
            [3] => d
        )

    [1] => Array
        (
            [0] => e
            [1] => f
            [2] => g
            [3] => h
        )

    [2] => Array
        (
            [0] => i
            [1] => j
            [2] => k
            [3] => l
        )

    [3] => Array
        (
            [0] => m
            [1] => n
            [2] => o
            [3] => p
        )

    [4] => Array
        (
            [0] => q
            [1] => r
        )

)

这将确保组在任何时候都不会超过 5 个元素,而另一个没有限制

使用的功能

function alternate_chunck($array, $parts) {
    $t = 0;
    $result = array();
    $max = ceil(count($array) / $parts);
    foreach(array_chunk($array, $max) as $v) {
        if ($t < $parts) {
            $result[] = $v;
        } else {
            foreach($v as $d) {
                $result[] = array($d);
            }
        }
        $t += count($v);
    }
    return $result;
}


function fill_chunck($array, $parts) {
    $t = 0;
    $result = array_fill(0, $parts - 1, array());
    $max = ceil(count($array) / $parts);
    foreach($array as $v) {
        count($result[$t]) >= $max and $t ++;
        $result[$t][] = $v;
    }
    return $result;
}

【讨论】:

  • 不客气..但我不确定该功能是否会在所有可能的情况下为您提供帮助...查看更新以了解其他可能性..如果您有任何问题,请告诉我...跨度>
  • 如何循环遍历每个array_chunk?谢谢
【解决方案2】:

请允许我第一个提供基于数学的无环解决方案。

数学中的魔力在于确定元素的哪些部分属于第一组块,其中所有列都填充在每一行中,哪些元素属于第二组(如果该组甚至应该存在),其中除了最右边的列已填满。

让我画出我在说什么。 &gt; 标志着两个分块数组之间的划分。

$size = 9;        -------------    $size = 9;        -------------
$maxRows = 4;   1 | A , B , C |    $maxRows = 3;     | A , B , C |
$columns = 3;   > |-----------|    $columns = 3;   1 | D , E , F |
$fullRows = 1;    | D , E |        $fullRows = 3;    | G , H , I |
                2 | F , G |                        > -------------
                  | H , I |                        2      n/a
                  ---------


$size = 18;        ---------    $size = 17;       -------------------------------------
$maxRows = 12;     | A , B |    $maxRows = 2;   1 | A , B , C , D , E , F , G , H , I |
$columns = 2;      | C , D |    $columns = 9;   > -------------------------------------
$fullRows = 6;     | E , F |    $fullRows = 1;  2 | J , K , L , M , N , O , P , Q |
                 1 | G , H |                      ---------------------------------
                   | I , J |
                   | K , L |
                 > ---------
                   | M |
                   | N |
                   | O |
                 2 | P |
                   | Q |
                   | R |
                   -----

代码:(Demo)

function double_chunk($array, $maxRows) {
    $size = count($array);
    $columns = ceil($size / $maxRows);
    $lessOne = $columns - 1;
    $fullRows = $size - $lessOne * $maxRows;
    
    if ($fullRows == $maxRows) {
        return array_chunk($array, $fullRows);  // all columns have full rows, don't splice
    }
    return array_merge(
               array_chunk(
                   array_splice($array, 0, $columns * $fullRows),  // extract first set to chunk
                   $columns
               ),
               array_chunk($array, $lessOne)   // chunk the leftovers
           );
}
var_export(double_chunk(range('a', 'i'), 3));

如果您不介意重复的 array_splice() 调用,这更简短,也许更容易理解(......也许不是):

代码:(Demo)

function custom_chunk($array, $maxRows) {
    $size = count($array);
    $columns = ceil($size / $maxRows);
    $lessOne = $columns - 1;
    $fullRows = $size - $lessOne * $maxRows;
    
    for ($i = 0; $i < $maxRows; ++$i) {
        $result[] = array_splice($array, 0, ($i < $fullRows ? $columns : $lessOne));
    }
    return $result;
}
var_export(custom_chunk(range('a', 'r'), 12));

【讨论】:

  • 这似乎是所有答案中最详尽和准确的答案,只是回答得太晚了。但为我工作。 +1
【解决方案3】:

你可以使用array_chunkarray_merge来解决这个问题:

<?php 

$array = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r');
$chunked_arr = array_chunk($array,12);
$j = 0;
for($i = 0; $i < count($chunked_arr[0]); $i++){
    if(!($i % 2 == 0)){
        $first_combined[$j][$i % 2] = $chunked_arr[0][$i];
        $j++;
    } else {
    $first_combined[$j][$i % 2] = $chunked_arr[0][$i];
    }
}

$merged_array = array_merge($first_combined, $chunked_arr[1]); 

echo '<pre>';
print_r($merged_array);
 ?>

你会得到这样的结果:

Array
(
    [0] => Array
        (
            [0] => a
            [1] => b
        )

    [1] => Array
        (
            [0] => c
            [1] => d
        )

    [2] => Array
        (
            [0] => e
            [1] => f
        )

    [3] => Array
        (
            [0] => g
            [1] => h
        )

    [4] => Array
        (
            [0] => i
            [1] => j
        )

    [5] => Array
        (
            [0] => k
            [1] => l
        )

    [6] => m
    [7] => n
    [8] => o
    [9] => p
    [10] => q
    [11] => r
)

这正是你想要的。

Live Demo Here>>

【讨论】:

  • count($chunked_arr[0]) 应作为变量缓存,而不是在每次循环迭代后调用。关于$i % 2 的相同建议——你不应该要求 php 对相同的数据执行相同的计算。
【解决方案4】:

ceil(count($array) / $parts) 会给出 2,所以每个数组都被 2 个项目填充,直到你没有 2 个项目。因此最后一个有 1 个项目。当数组中有大量数据时,这将起作用,但当数据量很少时,这会起作用。

【讨论】:

    【解决方案5】:

    您所描述的不是 array_chunk 的用途。您应该使用array_slice() 并自己计算您希望将数组的哪些部分作为新数组结束。 (并使用 for 循环遍历您的原始数组)

    更新:

    一些可以帮助你的计算:

    minimum_fill = floor(array_length / nr_buckets)
    bigger_buckets_amount = array_length - (minimum_fill / nr_buckets)
    

    填满桶的算法: 遍历数组,用(minimum_fill + 1)填充第一个bigger_buckets_amount数量的桶,用minimum_fill填充其余的桶

    【讨论】:

    • 你能把这些提示具体化成一个完整的工作 sn-p 吗?
    【解决方案6】:

    编译它,看看它是否适合你:

    <?php
    
    $array = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm');
    
    $sliceA = 0;
    $sliceB = 2;
    
    $final = array(array_slice($array, $sliceA, $sliceB));
    
    
    for ($i=$sliceB; $i<sizeof($array); $i++)
    {
        $final[$sliceB-1] = array($array[$i]);
        $sliceB++;
    }
    
    var_dump($final);
    

    【讨论】:

    • OP 希望只提供输入数组和最大数量的子数组(可能有不相等的计数)。您的回答是需要输入数组加上$sliceAsliceB。请重新阅读问题。
    【解决方案7】:
    <?php
    $array = range('a','r');
    $length = array(2=>6,1=>6); // 2=>6 means -- first six elements of new array will have 2 elements each and then, 1=>6 means -- next six elements of new array will have 1 element each
    $target = array(); // or use []  in PHP 5.4
    foreach($length as $i=>$times) {
        while($times>0){
            $target[] = array_splice($array, 0, $i);
            $times--;
        }
    }
    print_r($target);
    ?>
    

    【讨论】:

    • 这不是很通用——它希望开发人员评估和硬编码首选的分块算法。如果你问我,那是没有帮助的。如果开发人员要费心去做这件事,他们为什么不直接手动定义所有新的数据结构呢?
    【解决方案8】:
    <?php
    function slotify($array, $length)
    {
        // Create a placeholder array and calculate the number of items
        // needed per slot (think card dealing LtoR).
        for(
            $slots = array_fill(0, $length, 0), $count=count($array), $i=0;
            $i<$count;
            $slots[$i % $length]++, $i++
        );
    
        // Now just take slices of the original array
        // depending on the calculated slot number and place in our slots
        foreach($slots as $k => $n) {
            $slots[$k] = array_splice($array, 0, $n);
        }
    
        return $slots;
    }
    
    var_export(slotify(['a','b','c','d','e','f'], 4));
    

    输出:

    array (
      0 => 
      array (
        0 => 'a',
        1 => 'b',
      ),
      1 => 
      array (
        0 => 'c',
        1 => 'd',
      ),
      2 => 
      array (
        0 => 'e',
      ),
      3 => 
      array (
        0 => 'f',
      ),
    )
    

    对于上面的示例,中间数组$slots 包含所需的项目数如下所示:

    array (
      0 => 2,
      1 => 2,
      2 => 1,
      3 => 1,
    )
    

    如果您研究中间数组的不同组合。您需要计算出块大小变化的边界点。我的解决方案倾向于以下,这几乎是 mickmacusa 的最终解决方案。但这需要理解问题。

    function slotify($array, $length)
    {
        $count      = count($array);
        $chunk_size = ceil($count/$length);
        $boundary   = $count % $length;
    
        if($boundary === 0)
            $boundary = $length;
    
        for($i=0; $i<$length; $i++) {
            if($i === $boundary)
                $chunk_size--;
            $result[$i] = array_splice($array, 0, $chunk_size);
        }
    
        return $result;
    }
    

    可以做进一步的改进,切片可能比拼接更有效,如果你可以在整个数组中均匀分布,你可以走捷径。

    【讨论】:

      【解决方案9】:

      这将为您解决!
      在这里,我使用函数 smallify() 将 15 个元素的数组分解为 3 个数组,每个数组包含 5 个元素。

      <?php
      
      $bigArray = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
      
      echo ("<pre>");
      print_r (smallify($bigArray, 3));
      echo ("<pre/>");
      
      
      function smallify($arr, $numberOfSlices){
      
        $sliceLength = sizeof($arr) /$numberOfSlices;
        for($i=1; $i<=$numberOfSlices; $i++){
      
             $arr1 = array_chunk($arr, $sliceLength*$i);
             return $arr1;
             unset($arr1);
      
         }
      
      }
      ?>
      

      结果

      Array
      (
      [0] => Array
          (
              [0] => 1
              [1] => 2
              [2] => 3
              [3] => 4
              [4] => 5
          )
      
      [1] => Array
          (
              [0] => 6
              [1] => 7
              [2] => 8
              [3] => 9
              [4] => 10
          )
      
      [2] => Array
          (
              [0] => 11
              [1] => 12
              [2] => 13
              [3] => 14
              [4] => 15
          )
      
      )
      

      【讨论】:

      • unset() 写在return 之后有什么用?如果您要在第一次迭代中杀死它,为什么还要麻烦循环呢?请提供一个有效的演示链接,因为这个答案闻起来不对。
      【解决方案10】:

      我认为问题在于您在使用 array_chunk 时使用了 2 的大小。这样可以确保创建的每个新数组在可能的情况下都有两个项目。这会导致函数在您达到 10 时用完要放入新数组的变量。您可以在此处找到函数手册 http://php.net/manual/en/function.array-chunk.php 希望这会有所帮助

      【讨论】:

      • 这是对问题的观察,但并不试图提供可行的解决方案。不是答案。
      【解决方案11】:

      您可以尝试使用以下简单功能吗?

      $cols = array2cols($array,12);

      function array2cols($array,$n){
          $groups = array();
          for($i=0;$i<$n;$i++){
              $groups[$i] = array();
          }
          $col = 0;
          foreach($array as $row){
              $groups[$col][] = $row;
              $col = ($col+1)%$n;
          }
          return $groups;
      }
      

      【讨论】:

      • 这不是想要的结果。证明:3v4l.org/Vn3UM 第一个子数组应该包含值ab,但是您的代码显示am。如果重新阅读问题没有帮助,请参阅我的答案中的图形表示。
      猜你喜欢
      • 2012-01-01
      • 1970-01-01
      • 2012-01-01
      • 2017-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多