I have array as follows
array (A => 1)
array (A => 1, B=>2)
array (A => 1, B=>2, C=>3)
array (A => 1, D=>4)
array (A => 1, E=>5)
array (A => 1, F=>6)
array (A => 1, F=>6, G=>8)
array (A => 1, F=>6, H=>9)
array (X => 11)
array (X => 11, Y=22)
array (X => 11, Z=33)
I need to form array as follows
array(A=>array(B=>2, C=>3, D=>4, E=>5, F=>array(G=>8,H=>9))
X=>array(Y=>22, Z=>33)
I think this is what you’re looking for:
$result = array();
foreach ($arrays as $array) {
$ref = &$result;
foreach ($array as $key => $val) {
if (!isset($ref[$key])) {
$ref[$key] = $val;
} elseif (!is_array($ref[$key])) {
$ref[$key] = array();
}
$ref = &$ref[$key];
}
}
Here the keys are interpreted as path segments to walk the array using a reference. If there is no value yet, the value is stored; if there already is a value, it is replaced by an array.
But this is generating a little different result:
array (
'A' =>
array (
'B' =>
array (
'C' => 3,
),
'D' => 4,
'E' => 5,
'F' =>
array (
'G' => 8,
'H' => 9,
),
),
'X' =>
array (
'Y' => 22,
'Z' => 33,
),
)
Related
This question already has answers here:
How to Flatten a Multidimensional Array?
(31 answers)
Closed 5 months ago.
I have following array keys values:
$arrData = array
(
array(
'a' => 'test',
'c' => 1,
'd' => 2,
'e' => 'B'
),
array(
'c' => 1,
'd' => 2,
'e' => 'B'
),
array(
'b' => 'test2',
'c' => 1,
'd' => 2,
'e' => 'B'
)
);
So here I need to merged array into single with combining missing keys with single value array.
Can someone please help to get following output in single array?
$arrData = array
(
array(
'a' => 'test',
'b' => 'test2',
'c' => 1,
'd' => 2,
'e' => 'B'
)
);
Thanking in advance!
Just merge them and then sort on the key:
$arrData = array_merge(...$arrData);
ksort($arrData);
Instead of ... you can use:
$arrData = call_user_func_array('array_merge', $arrData);
If you really want the result to be multi-dimensional, then:
$arrData = [$arraData];
//or
$arrData = array($arrData);
You can use array_reduce (or a simple foreach loop) to merge each of the subsequent array values with the first one:
$out = array_reduce($arrData, function ($c, $v) { return array_merge($c, $v); }, array());
print_r($out);
$out = array();
foreach ($arrData as $arr) {
$out = array_merge($out, $arr);
}
print_r($out);
Output (for both examples):
Array (
[a] => test
[c] => 1
[d] => 2
[e] => B
[b] => test2
)
If you want to keep the keys in alphabetical order, you can use ksort:
ksort($out);
print_r($out);
Array (
[a] => test
[b] => test2
[c] => 1
[d] => 2
[e] => B
)
Demo on 3v4l.org
Using array_walk and ksort
$res=[];
array_walk($arrData, function($v,$k) use(&$res){
$res = array_merge($res,$v);
});
ksort($res);
OR
You can use foreach and array_column
$keys = ['a','b','c','d','e'];
$res=[];
foreach($keys as $val){
$res[$val] = array_column($arrData, $val)[0];
}
print_r($res);
Live Demo
<?php
$arrData = array
(
array(
'a' => 'test',
'c' => 1,
'd' => 2,
'e' => 'B'
),
array(
'c' => 1,
'd' => 2,
'e' => 'B'
),
array(
'b' => 'test2',
'c' => 1,
'd' => 2,
'e' => 'B'
)
);
$result_array = array();
foreach($arrData as $ad){
foreach($ad as $key=>$value){
if(!array_key_exists($key,$result_array)){
$result_array[$key] = $value;
}
}
}
print_r($result_array);
?>
I have the following multidimensional array. I had to create keys the way it looks to group them accordingly.
Array
(
[Oranges] => Array
(
[Name] => Oranges
[l.VA123] => 17
[l.MA123] => 12
[l.GA123] => 9
[l.CT123] => 5
)
[Apple] => Array
(
[Name] => Apple
[l.CA123] => 13
)
[Grapes] => Array
(
[Name] => Grapes
[l.WI123] => 8
[l.FL123] => 5
)
)
However, I need all the subarrays to have the same keys. Missing ones should be filled with a value of 0. The final array should be like below so that all subarrays have equal length.
Array
(
[Oranges] => Array
(
[Name] => Oranges
[l.VA123] => 17
[l.MA123] => 12
[l.GA123] => 9
[l.CT123] => 5
[l.CA123] => 0
[l.WI123] => 0
[l.FL123] => 0
)
[Apple] => Array
(
[Name] => Apple
[l.CA123] => 13
[l.WI123] => 0
[l.FL123] => 0
[l.VA123] => 0
[l.MA123] => 0
[l.GA123] => 0
[l.CT123] => 0
)
[Grapes] => Array
(
[Name] => Grapes
[l.WI123] => 8
[l.FL123] => 5
[l.CA123] => 0
[l.VA123] => 0
[l.MA123] => 0
[l.GA123] => 0
[l.CT123] => 0
)
)
You need a simple + operator. As from manual:
The + operator returns the right-hand array appended to the left-hand array; for keys that exist in both arrays, the elements from the left-hand array will be used, and the matching elements from the right-hand array will be ignored.
$items = Array
(
'Oranges' => Array
(
'Name' => 'Oranges',
'l.VA123' => 17,
'l.MA123' => 12,
'l.GA123' => 9,
'l.CT123' => 5,
),
'Apple' => Array
(
'Name' => 'Apple',
'l.CA123' => 13,
),
'Grapes' => Array
(
'Name' => 'Grapes',
'l.WI123' => 8,
'l.FL123' => 5,
),
);
// static keys
$keys = [
'l.VA123' => 0,
'l.MA123' => 0,
'l.GA123' => 0,
'l.CT123' => 0,
'l.CA123' => 0,
'l.WI123' => 0,
'l.FL123' => 0,
];
// keys generated from source array, tricky approach
$keys = array_fill_keys(
// here we merge all elements of `$items` into one array
// as keys are repeated - you definitely got all keys that
// can be in `$items`, `array_keys` will give you these keys
// `array_fill_keys` will create array where key is what you need
// and value is 0.
array_keys(call_user_func_array('array_merge', $items)),
0
);
// keys generated from source array, SIMPLE approach
$keys = [];
foreach ($items as $item) {
foreach ($item as $k => $v) {
if ($k != 'Name') {
$keys[$k] = 0;
}
}
}
foreach ($items as &$item) {
$item = $item + $keys;
}
print_r($items);
Probably someone can come up with something more efficient, but without a list of keys that you want, I think you'll need to take a couple of passes of the array:
<?php
$fruits = [
"Oranges"=>["Name"=>"Oranges", "l.VA123"=>17, "l.MA123"=>12, "1.GA123"=>9, "1.CT123"=>5],
"Apple"=>["Name"=>"Apple", "1.CA123"=>13],
"Grapes"=>["Name"=>"Grapes", "1.WI123"=>8, "1.FL123"=>5]
];
$keys = [];
foreach ($fruits as $fruit) {
unset($fruit["Name"]);
$keys = array_merge($keys, array_keys($fruit));
}
$keys = array_fill_keys(array_unique($keys), 0);
foreach ($fruits as &$fruit) {
$fruit = array_merge($keys, $fruit);
}
print_r($fruits);
Since all keys and default values are "known", create an associative array, use a foreach() and modify the rows by reference, and use the union-assignment (combined) operator. This will allow the original values to overwrite the default values.
Code: (Demo)
$keys = [
'l.VA123' => 0,
'l.MA123' => 0,
'l.GA123' => 0,
'l.CT123' => 0,
'l.CA123' => 0,
'l.WI123' => 0,
'l.FL123' => 0,
];
foreach ($items as &$row) {
$row += $keys;
}
var_export($items);
If you want the keys to be consistently positioned, then use array_replace() or array_merge() instead of the union assignment operator.
Code: (Demo)
foreach ($items as &$row) {
$row = array_replace($keys, $row);
}
I would like to subtract the quantity of $array2 from the stocks of $array1.
$array1= ([product_id]=>4, [stocks]=>20)
$array2= ([product_id]=>4, [quantity]=>3)
So that would be:
$array1= ([0]=> 4, [1] => 20);
$array2= ([0]=> 4, [1] => 3);
And then the output should be:
$array1= ([0]=> 4, [1] => 17);
Your array structure looks slightly different with multiple records, the code works out like this in an ugly manner. I'm assuming you're talking about something like this:
$array1 = array(
0=>array('product_id'=>4, 'stocks'=>20),
1=>array('product_id'=>5, 'stocks'=>60));
$array2 = array(
0=>array('product_id'=>4, 'quantity'=>3)
1=>array('product_id'=>5, 'quantity'=>30));
...It's a multi-dimensional array (typical for records pulled from a database).
foreach($array1 as $key=>$value){
foreach($array2 as $key2=>$value2) {
if($value['product_id']==$value2['product_id']){
$value['stocks'] -= $value2['quantity'];
//optimization to avoid searching this again.
unset($array2[$key]);
}
}}
With what you have given the following will do what you are asking for:
if($array1['product_id'] == $array2['product_id']) {
$array1['stocks'] -= $array2['quantity'];
}
If you need to loop through a bigger array then what I have given is only part of the larger puzzle.
Jesse's answer wasn't tested and will not provide the desired output because the "stocks" array wasn't being modified -- a copy of the array was being modified in the loop -- so if you try to print the result to screen, there would be no change.
To modify by reference, use & just before the value variable in the first loop.
Also the unset() key must come from the inner loop to be accurate.
Additionally, if the "sales" "product_id"s are unique, then breaking the inner loop upon matching will improve performance. (This is how array_search() works.)
Code: (Demo)
$stocks = [
['product_id'=>2, 'stocks'=>50],
['product_id'=>3, 'stocks'=>100],
['product_id'=>4, 'stocks'=>20],
['product_id'=>5, 'stocks'=>60]
];
$sales = [
['product_id'=>4, 'quantity'=>3],
['product_id'=>5, 'quantity'=>30]
];
foreach ($stocks as &$row) { // modify by reference
foreach ($sales as $k => $row2) { // search for product_id match
if ($row['product_id'] == $row2['product_id']) {
$row['stocks'] -= $row2['quantity']; // subtract
unset($sales[$k]); // eliminate match from lookup array
break; // assuming $sales['product_id'] values are unique
}
}
}
var_export($stocks);
Output:
array (
0 =>
array (
'product_id' => 2,
'stocks' => 50,
),
1 =>
array (
'product_id' => 3,
'stocks' => 100,
),
2 =>
array (
'product_id' => 4,
'stocks' => 17,
),
3 =>
array (
'product_id' => 5,
'stocks' => 30,
),
)
Alternatively, you can converted the sales array into a flattened, product_id-keyed array to serve as a lookup.
Code: (Demo)
$keyed = array_column($sales, 'quantity', 'product_id');
var_export($keyed);
echo "\n---\n";
foreach ($stocks as &$row) { // modify by reference
if (isset($keyed[$row['product_id']])) { // search for product_id match
$row['stocks'] -= $keyed[$row['product_id']]; // subtract
}
}
var_export($stocks);
Output:
array (
4 => 3,
5 => 30,
)
---
array (
0 =>
array (
'product_id' => 2,
'stocks' => 50,
),
1 =>
array (
'product_id' => 3,
'stocks' => 100,
),
2 =>
array (
'product_id' => 4,
'stocks' => 17,
),
3 =>
array (
'product_id' => 5,
'stocks' => 30,
),
)
I have 1 array that has the right values that I need but it is out of order. I then have another array with the same keys and it is in the right order but the values are not what I need.
Here is my first array with the correct values but is out of order:
Array
(
[countTotal] => 7268
[zip] =>
[yearName] =>
[countZipRadius] =>
[Acura] => 1334
[Cadillac] => 511
[Ford] => 5423
)
Here is my second array with the right order but the wrong values:
Array
(
[countZipRadius] => 0
[zip] => 1
[yearName] => 2
[Acura] => 3
[Cadillac] => 4
[Ford] => 5
[countTotal] => 6
)
I am trying to figure out a way to create a new array with the right values from array 1 but that is in the order of array 2.
I have been playing with it for awhile and cannot seem to get it.
Any help would be great.
Thanks!
$c = array();
foreach (array_keys($b) as $k) {
$c[k] = $a[k];
}
You could use php's array_multisort function:
$original = array(
'countTotal' => 7268,
'zip' => '',
'yearName' => '',
'countZipRadius' => '',
'Acura' => 1334,
'Cadillac' => 511,
'Ford' => 5423,
);
$right = array(
'countZipRadius' => 0,
'zip' => 1,
'yearName' => 2,
'Acura' => 3,
'Cadilac' => 4,
'Ford' => 5,
'countTotal' => 6
);
//make sure both arrays are in the same order
ksort($original);
ksort($right);
array_multisort($right, $original);
print_r($original);
When you give it two arrays with the same number of elements it sorts both arrays, based on the order of the first array - in this case the 0, 1, 2, 3, etc. values in $right
Create a New Array (Array C)
Use a FOR loop to go through Array B
For each value in Array B, get the value with the same key from Array A and set Array C append those values to Array C. This will put them in the correct order in C.
Using scones' method:
$original = array(
'countTotal' => 7268,
'zip' => '',
'yearName' => '',
'countZipRadius' => '',
'Acura' => 1334,
'Cadillac' => 511,
'Ford' => 5423,
);
$right = array(
'countZipRadius' => 0,
'zip' => 1,
'yearName' => 2,
'Acura' => 3,
'Cadilac' => 4,
'Ford' => 5,
'countTotal' => 6
);
foreach ($right as $key => $value) {
$new[$key] = $original[$key];
}
print_r($new);
$array = array('a' => 100, 'b' => '5');
$newArray = array_combine(array_keys($array), range(0, count($array) - 1));
var_dump($newArray);
I have an initial array:
$arr0 = array(
0 => array(
'a' => 1,
'b' => 1
)
1 => array(
'a' => 2,
'b' => 1
)
2 => array(
'a' => 3,
'b' => 2
)
3 => array(
'a' => 4,
'b' => 3
)
4 => array(
'a' => 5,
'b' => 3
)
);
I wish to divide it into separate arrays depending on its members' value of the field 'b', like so:
// $arr1 contains $arr0[0] and $arr0[1] because their value of 'b' is 1.
$arr1 = array(
0 => array(
'a' => 1,
'b' => 1
)
1 => array(
'a' => 2,
'b' => 1
)
);
// $arr2 contains $arr0[2] because its value of 'b' is 2.
$arr2 = array(
0 => array(
'a' => 3,
'b' => 2
)
);
// $arr3 contains $arr0[3] and $arr0[4] because their value of 'b' is 3.
$arr3 = array(
0 => array(
'a' => 4,
'b' => 3
)
1 => array(
'a' => 5,
'b' => 3
)
);
Now, the field 'b' can have any natural number for value, so it is not always three resulting arrays that I will need.
I have found a related question (and answers) here, but my problem is specific because I don't know in advance what original values 'b' has, and how many of different values there are.
Any ideas?
(edit: $arr3 was written as $arr1)
foreach ($arr0 as $value) {
${"arr" . $value['b']}[] = $value;
}
// $arr1, $arr2 and $arr3 are defined
There is magic in the second line, which dynamically builds a variable name. However, that way of programming is really unwieldy; you would do better to make the results into yet another array, like this:
foreach ($arr0 as $value) {
$allarr[$value['b']][] = $value;
}
// $allarr is defined
foreach ($arr0 as $val) {
$b = $val ['b'];
if (!$arr$b) $arr$b = array();
$arr$b[] = $val;
}