Related
I am new in php.I have learn almost all things in php.I am developing sample application in php. In my application I have two arrays and it looks like:
Array
(
[0] => 1800
[5] => 1500
[6] => 4545
)
Array
(
[0] => a
[1] => b
[2] => c
[3] => d
[4] => e
[5] => f
[6] => g
)
I want output like:
Array
(
[0] => Array
(
[a] => 1800
)
[1] => Array
(
[b] => 0
)
[2] => Array
(
[c] => 0
)
[3] => Array
(
[d] => 0
)
[4] => Array
(
[e] => 0
)
[5] => Array
(
[f] => 1500
)
[6] => Array
(
[g] => 4545
)
)
Please help.
Found solution for your question.
<?php
$arr1 = array(
'0' => '1800',
'5' => '1500',
'6' => '4545'
);
$arr2 = array(
'0' => 'a',
'1' => 'b',
'2' => 'c',
'3' => 'd',
'4' => 'e',
'5' => 'f',
'6' => 'g',
);
$arr3 = array();
foreach($arr2 as $key => $value){
if(!empty($arr1[$key])){
$arr3[$key][$value] = $arr1[$key];
}
else{
$arr3[$key][$value] = 0;
}
}
print '<pre>';
print_r($arr3);
print'</pre>';
?>
$arr1 = array(0 => 1800, 5 => 1500, 6 => 4545,);
$arr2 = array('a', 'b', 'c', 'd', 'e', 'f', 'g',);
$arrNeeded = array();
foreach ($arr2 AS $k => $v) {
$arrNeeded[$k] = array($v => isset($arr1[$k]) ? $arr1[$k] : 0);
}
echo '<pre>' . print_r($arrNeeded, true) . '</pre>';
Please try with below code
$arr1 = array( 0 => 1800 ,5 => 1500 ,6=> 4545 );
$arr2 = array( 0 => 'a' ,1 => 'b', 2=> 'c',3 => 'd' ,4 => 'e' ,5 => 'f' ,6 => 'g' );
$newarr = "";
if(count($arr2) >0){
foreach($arr2 as $key2 => $val2){
$newVal = isset($arr1[$key2])?$arr1[$key2] : 0;
$newarr[$key2] = array($val2 => $newVal);
}
}
echo "<pre>";
print_r($newarr);
This might help you
<?php
$array1 = Array( "0"=>1800,"5" => 1500, "6" => 4545 ) ;
$array2 = Array( "0" => 'a', '1' => 'b', '2' => 'c', '3' => 'd', '4' => 'e', '5' => 'f', '6' => 'g' );
$resultArray = array();
foreach ($array2 as $key2 => $value2 ) {
$found = false;
foreach ($array1 as $key1 => $value1) {
if($key1 == $key2){
$resultArray[$value2] = $value1;
$found = true;
continue;
}
if(!$found)
{
$resultArray[$value2] = 0;
}
}
}
print_r($resultArray);
?>
I have two multi-dimensional arrays. I need to concatenate the two without loosing any values which have the same key and different values. Here is the scenario:
Array1
(
[0] => 11
[2] => 12
[3] => 13
[4] => (
[0] => 100
[1] => 200
)
[5] => 2
[6] => 3
)
Array2
(
[0] => 11
[2] => 12
[3] => 13
[4] => (
[0] => 400
[1] => 500
)
[5] => 2
[6] => 3
)
The result should be
Result
(
[0] => 11
[2] => 12
[3] => 13
[4] => (
[0] => (
[0] => 100
[1] => 400
)
[1] => (
[0] => 200
[1] => 500
)
)
[5] => 2
[6] => 3
)
Here is one solution:
<?php
$arrayA = array(0 => 11, 2 => 12, 3 => 13, 4 => array(0 => 100, 1 => array(0 => 222),), 5 => 2, 6 => 3);
$arrayB = array(
0 => 11,
2 => 12,
3 => 13,
4 => array(
0 => 100,
1 => array(0 => array(0 => 'test1', 1 => 'test2'), 1 => array(0 => 'test1', 1 => 'test2'),),
),
5 => 2,
6 => 3
);
/**
* #param $a
* #param $b
* #return array
*/
function array_merge_graceful($a, $b)
{
$c = [];
if (is_array($a) && is_array($b)) {
foreach (array_merge(array_keys($a),array_keys($b)) as $i) {
if (!array_key_exists($i, $a)) {
$c[$i] = $b[$i];
} elseif (!array_key_exists($i, $b)) {
$c[$i] = $a[$i];
} else {
$c[$i] = array_merge_graceful($a[$i], $b[$i]);
}
}
} else {
if ($a <> $b) {
$c = [$a, $b];
} else {
$c = $a;
}
}
return $c;
}
var_dump(array_merge_graceful($arrayA, $arrayB));
?>
Try something like this
<?php
$array1 = array(11, 12, 13, array(100, 200), 2, 3);
$array2 = array(11, 12, 13, array(400, 500), 2, 3);
echo "<pre>";
print_r($array1);
print_r($array2);
$combine = array();
foreach ($array1 as $key => $value) {
if (array_key_exists($key, $combine)) {
//if is array
if (is_array($combine[$key])) {
$combine[$key] = array($combine[$key], $value);
}
} else {
$combine[$key] = $value;
}
}
foreach ($array2 as $key => $value) {
if (array_key_exists($key, $combine)) {
//if is array
if (is_array($combine[$key])) {
$combine[$key] = array($combine[$key], $value);
}
} else {
$combine[$key] = $value;
}
}
echo "<hr>";
print_r($combine);
use array_merge_recursive() function for merging arrays.For more details please refer http://php.net/manual/en/function.array-merge-recursive.php
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,....));
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',
)
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, ...);
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
)
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));
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 )
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.
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
)
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);
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)));
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Sort multidimensional array by multiple keys
I am trying to find some way how to sort array by key name, but nothing worked so far. The tricky part for me is to sort array by grouping 3 keys. I have this array.
[0] => Array
(
[id] => 8
[zbo_data] => blah
)
[1] => Array
(
[id] => 6
[szn_data] => blah
)
[2] => Array
(
[id] => 5
[gcz_data] => blah
)
[3] => Array
(
[id] => 3
[gcz_data] => blah
)
[4] => Array
(
[id] => 2
[zbo_data] => blah
)
[5] => Array
(
[id] => 1
[szn_data] => blah
)
And I need to sort it by group of 3 in this order: szn_data, zbo_data, gcz_data but I also need to keep the order of [id] (basically primary order by szn_data, zbo_data, gcz_data, secondary [id]). Is there a solution? Or should I construct array differently to be able to sort it? I am trying to figure this out for over 6 hours. Any help is much appreciated.
My desired output is:
[0] => Array
(
[id] => 6
[szn_data] => blah
)
[1] => Array
(
[id] => 8
[zbo_data] => blah
)
[2] => Array
(
[id] => 5
[gcz_data] => blah
)
[3] => Array
(
[id] => 1
[szn_data] => blah
)
[4] => Array
(
[id] => 2
[zbo_data] => blah
)
[5] => Array
(
[id] => 3
[gcz_data] => blah
)
Use usort and implement your comparison function as you wish. For example:
$result = usort($arr, function($a,$b) {
$keys = array('szn_data', 'zbo_data', 'gcz_data');
foreach ($keys as $key) {
// make sure to add here handling of missing keys
$diff = strcmp($b[$key], $a[$key]);
if ($diff!=0) {
return $diff;
}
}
return $b['id'] - $a['id'];
});
Or like this, for any order from max to the min listed in one array
$arr = array (
array(
'id' => 8,
'zbo_data' => 'blah'
),
array(
'id' => 6,
'szn_data' => 'blah'
),
array(
'id' => 5,
'gcz_data' => 'blah'
),
array(
'id' => 3,
'gcz_data' => 'blah'
),
array(
'id' => 2,
'zbo_data' => 'blah'
),
array(
'id' => 1,
'szn_data' => 'blah'
)
);
usort($arr, "my_func");
var_dump($arr);
function my_func($a, $b)
{
$vars = array('szn_data', 'zbo_data', 'gcz_data'); // order of the keys
$id1 = $a['id']; $id2 = $b['id']; unset($a['id'], $b['id']);
$index1 = array_search(key($a), $vars);
$index2 = array_search(key($b), $vars);
if ($index1 == $index2) {
if ($id1 == $id2) return 0;
return ($id1 < $id2) ? 1 : -1;
}
return ($index1 < $index2) ? -1 : 1;
}
ps:
basically primary order by szn_data, zbo_data, gcz_data, secondary
[id]
It does not correspond to your desired output. Secondary means comparison of id when other keys are the same.
ps: Updated - this code is NOT nice or perfect, but it will give you what you need
$vars = array('szn_data', 'zbo_data', 'gcz_data');
$arr = array (
array(
'id' => 8,
'zbo_data' => 'blah'
),
array(
'id' => 6,
'szn_data' => 'blah'
),
array(
'id' => 5,
'gcz_data' => 'blah'
),
array(
'id' => 3,
'gcz_data' => 'blah'
),
array(
'id' => 2,
'zbo_data' => 'blah'
),
array(
'id' => 1,
'szn_data' => 'blah'
)
);
$temp = array();
$cnt = count($arr);
foreach($arr as $item)
{
foreach($vars as $v)
{
if (isset($item[$v])) { $temp[$v][$item['id']] = $item; break; }
}
}
// sort by id
foreach($vars as $v)
{
krsort($temp[$v]);
$temp[$v] = array_values($temp[$v]);
}
$arr = array(); $i = 0; $j = 0;
$completed = false;
do {
foreach($vars as $v)
{
if ($i++>=$cnt) { $completed = true; break; }
if (isset($temp[$v][$j])) $arr[] = $temp[$v][$j];
}
$j++;
} while (!$completed);
// output
var_dump($arr)
I would like to be able to sort this array by the element array's size;
array(
[0] => array( [0] => 'B', [1] => 'C');
[1] => array( [0] => 'B');
[2] => array( [0] => 'A', [1] => 'C');
[3] => array( [0] => 'A', [1] => 'B', [2] => 'C');
[4] => array( [0] => 'C');
[5] => array( [0] => 'A');
[6] => array( [0] => 'A', [1] => 'B');
)
array(
[0] => array( [0] => 'A');
[1] => array( [0] => 'B');
[2] => array( [0] => 'C');
[3] => array( [0] => 'A', [1] => 'B');
[4] => array( [0] => 'A', [1] => 'C');
[5] => array( [0] => 'B', [1] => 'C');
[6] => array( [0] => 'A', [1] => 'B', [2] => 'C');
)
Using closures (PHP 5.3):
usort($array, function($a, $b) { return count($a) - count($b); });
Without using closures (PHP 5.2):
usort($array, create_function('$a, $b', 'return count($a) - count($b)'));
Note that $array will be sorted in place. Don't look for it in the return value of usort().
I have not tested this, but I hope you can get the point.
function yoursort($a,$b) {
if(!(is_array($a) && is_array($b)) return 0; // item of array is not an array
$cntA = sizeof($a);
$cntB = sizeof($b);
if($cntA!=$cntB) return $cntA-$cntB; // smaller array up
foreach($a as $key=>$val) {
$ordA = ord($a[$key]);
$ordB = ord($b[$key]);
if($ordA!=$ordB) return $ordA-$ordB; // sort sub array by alphabet
}
return 0; // items are equal
}
usort($yourarray,"yoursourt");
Here you can find more about usort
http://php.net/manual/en/function.usort.php
You can do this in 2 steps.
In step 1, sort individual arrays on
value.
In step 2, sort the 2D array, first
based on size and if the size are not
equal sort on the values.
Code:
foreach($input as $key => $val) {
sort($input[$key]);
}
usort($input, "cmp");
print_r($input);
function cmp($a,$b) {
if(count($a) != count($b)) {
return count($a) - count($b);
}
for($i=0;$i<count($a);$i++) {
if($a[$i] != $b[$i]) {
return strcmp($a[$i],$b[$i]);
}
}
return 0;
}
Code in Action