如何合并多个未知长度的平面数组,转置它们,然后形成一个一维数组


How can I merge multiple flat arrays of unknown length, transpose them, then form a 1-dimensional array?

我有 3 个这样的数组:

$a = array(
 0 => 'a1',
 1 => 'a2',
 2 => 'a3'
);
$b = array(
 0 => 'b1',
 1 => 'b2',
 2 => 'b3'
);
$c = array(
 0 => 'c1',
 1 => 'c2',
 2 => 'c3'
);

我喜欢这样的东西:

$r = array(
 0 => 'a1',
 1 => 'b1',
 2 => 'c1',
 3 => 'a2',
 4 => 'b2',
 5 => 'c2',
 6 => 'a3',
 ....
 ...
);

我怎样才能做到这一点并享受使用超过 3 个输入数组的能力?

编辑:

我试过这个:

$a = array(
        0 => 'a1',
        1 => 'a2',
        2 => 'a3',
        3 => 'a4'
    );
    $b = array(
        0 => 'b1',
        1 => 'b2',
        2 => 'b3'
    );
    $c = array(
        0 => 'c1',
        1 => 'c2',
        2 => 'c3',
        3 => 'c4',
        4 => 'c5',
        5 => 'c6'
    );
    $l['a'] = count($a);
    $l['b'] = count($b);
    $l['c'] = count($c);
    arsort($l);
    $largest = key($l);
    $result = array();
    foreach ($$largest as $key => $value) {
        $result[] = $a[$key];
        if(array_key_exists($key, $b)) $result[] = $b[$key];
        if(array_key_exists($key, $c)) $result[] = $c[$key];
    }
    print_r($result);

输出:Array ( [0] => a1 [1] => b1 [2] => c1 [3] => a2 [4] => b2 [5] => c2 [6] => a3 [7] => b3 [8] => c3 [9] => a4 [10] => c4 [11] => [12] => c5 [13] => [14] => c6 )

这有效,但代码不好。有人有更好的解决方案吗?

溶液:我用一些动态功能更新了@salathe的帖子

function comb(){
    $arrays = func_get_args();
    $result = array();
    foreach (call_user_func_array(array_map, $arrays) as $column) {
        $values = array_filter($column, function ($a) { return $a !== null; });
        $result = array_merge($result, $values);
    }
    return $result;
}
print_r(comb(null,$a,$b,$c,$d,....));

您可以使用array_map()函数来完成大部分艰苦的工作。

在示例中,循环中的代码只是从每个数组中获取值(如果没有相应的值,则null),如果有值,则将它们附加到$results数组中。

$result = array();
foreach (array_map(null, $a, $b, $c) as $column) {                                          
    $values = array_filter($column, function ($a) { return $a !== null; });
    $result = array_merge($result, $values);
}
var_export($result);

输出

array (
  0 => 'a1',
  1 => 'b1',
  2 => 'c1',
  3 => 'a2',
  4 => 'b2',
  5 => 'c2',
  6 => 'a3',
  7 => 'b3',
  8 => 'c3',
  9 => 'a4',
  10 => 'c3',
  11 => 'c3',
  12 => 'c3',
)

需要一些编码:

function customMerge()
{
    $arrays = func_get_args();
    $res = array();
    $continue = true;
    while($continue){
       $continue = false;
       for($j=0;$j<count($arrays); $j++){
          if($pair = each($arrays[$j]){
              if(is_numeric($pair[0])
                  $res[] = $pair[1];
              else
                  $res[ $pair[0] ] = $pair[1];
              $continue = true;
          }
       }
    }
    return $res;
}  
$res = customMerge($arr1, $arr2, $arr3, ...);

对不起我之前的回答,误读了问题。 以下是您的需求:

$arrays = array($a,$b,$c);
$new = array();
$count = count($arrays);
while(count($arrays) > 0) {
    for($i = 0; $i < $count; $i++) {
        if (isset($arrays[$i])) {
        array_push($new, array_shift($arrays[$i]));
        if (count($arrays[$i]) == 0) {
            unset($arrays[$i]);
            }
        }
    }
}

即使对于大小不相等的数组:

$a = array(
 0 => 'a1',
 1 => 'a2',
 2 => 'a3',
 3 => 'a4'
);
$b = array(
 0 => 'b1',
 1 => 'b2',
 2 => 'b3'
);
$c = array(
 0 => 'c1',
 1 => 'c2',
 2 => 'c3',
 3 => 'c4'
);

你会得到结果:

Array
(
    [0] => a1
    [1] => b1
    [2] => c1
    [3] => a2
    [4] => b2
    [5] => c2
    [6] => a3
    [7] => b3
    [8] => c3
    [9] => a4
    [10] => c4
)

你可以做这样的事情:

function getMaxLength(array $arrays) {
    $len = count($arrays);
    if($len == 0) {
        return 0;
    }
    $max = count($arrays[0]);
    for($i = 1; $i < $len; $i++) {
        $count = count($arrays[$i]);
        if($count > $max) {
            $max = $count;
        }
    }
    return $max;
}
function combine() {
    $arrays = func_get_args();
    $maxLength = getMaxLength($arrays);
    $combined = array();
    for($i = 0; $i < $maxLength; $i++) {
        foreach($arrays as $array) {
            if(isset($array[$i])) {
                $combined[] = $array[$i];
            }
        }
    }
    return $combined;
}
print_r(combine($a, $b, $c));

这个逻辑很糟糕。虽然有效

<?php
$a = array(
    0 => 'a1',
    1 => 'a2',
    2 => 'a3'
);
$b = array(
    0 => 'b1',
    1 => 'b2',
    2 => 'b3'
);
$c = array(
    0 => 'c1',
    1 => 'c2',
    2 => 'c3',
    3 => 'c4',
    4 => 'c5' 
);
$val=5; //Size of the largest array  (largest array is c)
$d=array();
for($i=0;$i<$val;$i++)
{
    $d[]=$a[$i];
    $d[]=$b[$i];
    $d[]=$c[$i];
}
//Clearing empty values
foreach ($d as $key=>$value)
if (empty($value))
    unset($d[$key]);

 //Consecutive Keys 
       $finalArray = array_values($d);
       print_r($finalArray);

输出:

Array ( [0] => a1 [1] => b1 [2] => c1 [3] => a2 [4] => b2 [5] => c2 [6] => a3 [7] => b3 [8] => c3 [9] => c4 [10] => c5 )

假设count($a)=count($b)=count($c),这可以完成为:

<?php
   $var = array();
   for($i=0;$i<count($a);$i++)
   {
    array_push($var,$a[$i]);
    array_push($var,$b[$i]);
    array_push($var,$c[$i]);
    }
  print_r($var);
 ?>

这将导致:

Array ( [0] => a1 [1] => b1 [2] => c1 [3] => a2 [4] => b2 [5] => c2 [6] => a3 [7] => b3 [8] => c3 )

编辑:用于@eggyal
我试过了:

<?php
 $a = array(
    0 => 'a1',
    1 => 'a2',
    2 => 'a3',
    3 => 'a4'
);
$b = array(
    'x' => 'b1',
    'y' => 'b4',
    'z' => 'b3'
);
$c = array(
    0 => 'c1',
    'p' => 'c2',
    2 => 'c3',
    3 => 'c3',
    'q' => 'c3',
    5 => 'c3'
);
$d = array_merge($b,$a,$c);//place arrays in any order like $a,$b,$c or $b,$a,$c or $c,$b,$a
sort($d);
print_r($d);
?>

这导致:

Array ( [0] => a1 [1] => a2 [2] => a3 [3] => a4 [4] => b1 [5] => b3 [6] => b4 [7] => c1 [8] => c2 [9] => c3 [10] => c3 [11] => c3 [12] => c3 )

我不确定这是否让您满意。但是,我认为合并仍在发生。但是,它不会保留密钥。

可以通过排序来完成

$arr = array_merge($a,$b,$c);
foreach ($arr as $key => $val) {
  $numsort[$key] = substr($val,1);
  $charsort[$key] = substr($val,0,1);
}
array_multisort($arr, SORT_ASC, SORT_NUMERIC, $numsort, $arr, SORT_ASC, $charsort);
// result
Array
(
    [0] => a1
    [1] => b1
    [2] => c1
    [3] => a2
    [4] => b2
    [5] => c2
    [6] => a3
    [7] => b3
    [8] => c3
)

您的情况只是与某些特定的排序合并。所以明确的方法是:

  1. 合并数组
  2. 排序结果

代码示例:

$merged = array_merge($a, $b, $c);
usort($merged, function($left, $right) {
        if (substr($left, 1) == substr($right, 1)) {//if numbers equal check letters
                return (substr($left, 0, 1) < substr($right, 0, 1)) ? -1 : 1;
        }
        return (substr($left, 1) < substr($right, 1)) ? -1 : 1;
});
print_r($merged);

输出:

Array
(
    [0] => a1
    [1] => b1
    [2] => c1
    [3] => a2
    [4] => b2
    [5] => c2
    [6] => a3
    [7] => b3
    [8] => c3
)

还有更通用的解决方案(所有第一行都是后续的,所有第二行都是后续的......

$result = call_user_func_array('array_merge', array_map(
        function () {
                return array_filter(func_get_args(), function ($element) {
                                return $element !== null;
                });
        } , $a, $b, $c)
);

print_r($result);

在找到此页面之前,我回答了一个重复的问题。 我在下面的解决方案使用...$row作为输入数据,但对于这个问题,只需切换...$rows $a, $b, $c。 (此后,我删除了我的另一个答案,并使用此页面敲定了重复的问题。

我对功能性单行代码的想法(为了可读性,我已经拆分了它并用标签)如下。 请注意,早期过滤将意味着最小化"无用数据"处理,而后期过滤将减少函数调用。

使用贪婪/懒惰/虚假过滤进行后期过滤:(演示)

var_export(
    array_filter(          #remove nulls
        array_merge(       #flatten the unpacked elements
            ...array_map(  #unpack
                null,      #transpose
                ...$rows   #transpose
            )              #unpack
        )                  #flatten the unpacked elements    
    )                      #remove nulls
);

精简的单行语法:(演示)

var_export(array_filter(array_merge(...array_map(null, ...$rows))));

具有贪婪/懒惰/虚假过滤的中间过滤:(演示)

var_export(
    array_merge(              #flatten the unpacked elements
        ...array_filter(      #remove nulls from transposing then unpack
            array_map(        #transpose
                null,         #transpose
                ...$rows      #transpose
            )                 #transpose
        )                     #remove nulls from transposing then unpack
    )                         #flatten the unpacked elements
);

或者做早期过滤...(使用贪婪/懒惰/虚假过滤)

代码:(演示)

var_export(
    array_merge(                     #flatten the unpacked elements
        ...array_map(                #unpack
            function() {             #transpose discarding nulls
                return array_filter( #transpose discarding nulls
                    func_get_args()  #transpose discarding nulls
                );                   #transpose discarding nulls
            },                       #transpose discarding nulls
            ...$rows                 #transpose discarding nulls
        )                            #unpack
    )                                #flatten the unpacked elements
);

或者使用贪婪/懒惰/虚假过滤和更多"喷溅"的早期过滤:(演示)

var_export(
    array_merge(                         #flatten the unpacked elements
        ...array_map(                    #unpack
            function(...$v) {            #transpose discarding nulls
                return array_filter($v); #transpose discarding nulls
            },                           #transpose discarding nulls
            ...$rows                     #transpose discarding nulls
        )                                #unpack
    )                                    #flatten the unpacked elements
);

这是PHP7.4版本:(演示)

var_export(
    array_merge(                           #flatten the unpacked elements
        ...array_map(                      #unpack
            fn(...$v) => array_filter($v), #transpose discarding nulls
            ...$rows                       #transpose discarding nulls
        )                                  #unpack
    )                                      #flatten the unpacked elements
);

其浓缩为:

var_export(array_merge(...array_map(fn(...$v) => array_filter($v), ...$rows)));