问题
I have 3 arrays like this:
$a = array(
0 => 'a1',
1 => 'a2',
2 => 'a3'
);
$b = array(
0 => 'b1',
1 => 'b2',
2 => 'b3'
);
$c = array(
0 => 'c1',
1 => 'c2',
2 => 'c3'
);
and I like to have something like this:
$r = array(
0 => 'a1',
1 => 'b1',
2 => 'c1',
3 => 'a2',
4 => 'b2',
5 => 'c2',
6 => 'a3',
....
...
);
How can I do this AND enjoy the ability to use more then 3 input arrays?
EDIT:
I have tried this:
$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);
Output: 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 )
This works but the code isn't nice. Does anyone have a better solution?
Solution: I updated the post from @salathe with some dynamic feature
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,....));
回答1:
You could make use the array_map() function to do most of the hard work.
In the example, the code inside the loop just takes the value from each array (null
if there is not a corresponding value) and if there is a value, appends them to the $results
array.
Example
$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);
Output
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',
)
回答2:
Need some coding:
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, ...);
回答3:
sorry for my previous answer, misread the question. here's what you need:
$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]);
}
}
}
}
even for the arrays with not equal sizes:
$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'
);
you'll get the result:
Array
(
[0] => a1
[1] => b1
[2] => c1
[3] => a2
[4] => b2
[5] => c2
[6] => a3
[7] => b3
[8] => c3
[9] => a4
[10] => c4
)
回答4:
You could do something like this:
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));
回答5:
This logic sucks.. Works though
<?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);
OUTPUT :
Array ( [0] => a1 [1] => b1 [2] => c1 [3] => a2 [4] => b2 [5] => c2 [6] => a3 [7] => b3 [8] => c3 [9] => c4 [10] => c5 )
回答6:
Assumed count($a)=count($b)=count($c)
, this can be done as:
<?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);
?>
This will result in:
Array ( [0] => a1 [1] => b1 [2] => c1 [3] => a2 [4] => b2 [5] => c2 [6] => a3 [7] => b3 [8] => c3 )
Edit: for @eggyal
I tried this out:
<?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);
?>
This resulted in:
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 )
I am not sure this satisfies you or not. But, i think the merging still takes place. However, it does not preserve the keys.
回答7:
Can be done with sorting
$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
)
回答8:
Your case is just merge with some specific ordering. So clear way to do that is:
- merge arrays
- sort result
Code example:
$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);
output:
Array
(
[0] => a1
[1] => b1
[2] => c1
[3] => a2
[4] => b2
[5] => c2
[6] => a3
[7] => b3
[8] => c3
)
There is more generic solution (all first rows are subsequent, all second rows all subsequent ...):
$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);
回答9:
I answered a duplicate before finding this page. My solutions below use ...$row
for the input data, but for this question just switch ...$rows
for $a, $b, $c
. (I have since deleted my other answer and hammered the duplicate question using this page.)
My thoughts on functional one-liners (I've split it and tabbed it for readability) are as follows. Note that early filtering will mean minimizing "useless data" handling and late filtering will make fewer function calls.
Late filtering with greedy/lazy/falsey filtering: (Demo)
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
);
Condensed one-liner syntax: (Demo)
var_export(array_filter(array_merge(...array_map(null, ...$rows))));
Intermediate filtering with greedy/lazy/falsey filtering: (Demo)
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
);
Or do early filtering... (with greedy/lazy/falsey filtering)
Code: (Demo)
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
);
Or early filtering with greedy/lazy/falsey filtering and more "splatting": (Demo)
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
);
And here is the PHP7.4 version: (Demo)
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
);
Which condenses as:
var_export(array_merge(...array_map(fn(...$v) => array_filter($v), ...$rows)));
来源:https://stackoverflow.com/questions/19478981/how-can-i-merge-multiple-flat-arrays-of-unknown-depth-transpose-them-then-form