I have this associative array
$data = array(
0=>array(
'id'=>1,
'cust_id'=>51,
'roomtype'=>'PREMIUM',
'start'=>'2018-12-20',
'end'=>'2018-12-25',
),
1=>array(
'id'=>2,
'cust_id'=>51,
'roomtype'=>'PRESIDENTIAL',
'start'=>'2018-12-26',
'end'=>'2019-01-01'
),
2=>array(
'id'=>3,
'cust_id'=>52,
'roomtype'=>'PREMIUM',
'start'=>'2019-01-08',
'end'=>'2019-'01-12'
)
3=>array(
'id'=>4,
'cust_id'=>52,
'roomtype'=>'DELUXE',
'start'=>'2019-01-13',
'end'=>'2019-'01-20'
),
4=>array(
'id'=>5,
'cust_id'=>53,
'roomtype'=>'DOUBLE',
'start'=>'2019-01-13',
'end'=>'2019-'01-25'
)
)
I wanted to get the number of times this cust_id had booked, and I wanted to add it in my other array, Im having a hard time as to how am I gonna get the number of iteration per customer based on the cust_id
My desired output:
$new = array(
0=>array(
'id'=>1,
'cust_id'=>51,
'roomtype'=>'PREMIUM',
'start'=>'2018-12-20',
'end'=>'2018-12-25',
'iteration'=>1
),
1=>array(
'id'=>2,
'cust_id'=>51,
'roomtype'=>'PRESIDENTIAL',
'start'=>'2018-12-26',
'end'=>'2019-01-01',
'iteration'=>2
),
2=>array(
'id'=>3,
'cust_id'=>52,
'roomtype'=>'PREMIUM',
'start'=>'2019-01-08',
'end'=>'2019-'01-12',
'iteration'=>1
)
3=>array(
'id'=>4,
'cust_id'=>52,
'roomtype'=>'DELUXE',
'start'=>'2019-01-13',
'end'=>'2019-'01-20',
'iteration'=>2
),
4=>array(
'id'=>5,
'cust_id'=>53,
'roomtype'=>'DOUBLE',
'start'=>'2019-01-13',
'end'=>'2019-'01-25',
'iteration'=>1
)
)
My sample code:
$i=1;
$new = array();
foreach ($data as $key=>$value) {
if ($value['cust_id'] == $value['cust_id']) {
$new[$key]['iteration']
$new[$key] = $value;
$i++;
}
}
Try this:
$usedIdsArr = [];
foreach ($data as $key => $row) {
if (!array_key_exists($row['cust_id'], $usedIdsArr)) {
$usedIdsArr[$row['cust_id']] = 1;
} else {
$usedIdsArr[$row['cust_id']]++;
}
$data[$key]['iteration'] = $usedIdsArr[$row['cust_id']];
}
I'm tracking all the ids and how many times they're used in $usedIdsArr. Each iteration I check if the id is in $usedIdsArr, if not, I add it with a value of one. If it is in $usedIdsArr, I increment the value. Then I add the key of 'iteration' to $data with the value I got from $usedIdsArr.
3v4l.org demo
I find this a much more efficient array.
array (
51 =>
array (
0 =>
array (
'id' => 1,
'cust_id' => 51,
'roomtype' => 'PREMIUM',
'start' => '2018-12-20',
'end' => '2018-12-25',
),
1 =>
array (
'id' => 2,
'cust_id' => 51,
'roomtype' => 'PRESIDENTIAL',
'start' => '2018-12-26',
'end' => '2019-01-01',
),
),
52 =>
array (
0 =>
array (
'id' => 3,
'cust_id' => 52,
'roomtype' => 'PREMIUM',
'start' => '2019-01-08',
'end' => '2019-01-12',
),
1 =>
array (
'id' => 4,
'cust_id' => 52,
'roomtype' => 'DELUXE',
'start' => '2019-01-13',
'end' => '2019-01-20',
),
),
53 =>
array (
0 =>
array (
'id' => 5,
'cust_id' => 53,
'roomtype' => 'DOUBLE',
'start' => '2019-01-13',
'end' => '2019-01-25',
),
),
)
https://3v4l.org/dpl2C
it's multidimensional and the key is the customer id. Inside each subarray you have all the bookings and can easily count on each customer.
In your array you need to find the maximum value of each customer id.
I can just echo count($new[52]); to get the number of bookings for "52".
You can get that from this code:
foreach($data as $sub){
$new[$sub['cust_id']][]= $sub;
}
var_export($new);
Related
I have two arrays, $array1 and $array2. $array2 is an array of arrays. For each subarray of $array2, I want to print $array1 but with additional entries that depend on whether the $array2 subarray has keys "a" or "c" with value 1. My code prints $array1 each loop, but there are additional entries in $array1 for the later iterations that I wasn't expecting. Why do I get these entries, and how do I prevent them?
Sample code:
$array1 = array(
"service" => "coding",
"data" => array(
"ITEM" => array(
array(
"CODE" => "9999", //STANDARD
"QUANTITY" => 1
),
)
)
);
$array2 = array(
array(
"a" => "1",
"b" => "1",
"c" => "1",
"d" => "1",
),
array(
"cancel" => "1",
"a" => "1",
"b" => "",
"c" => "",
"d" => "1",
),
array(
"cancel" => "1",
"a" => "",
"b" => "1",
"c" => "1",
"d" => "",
),
);
for ($i = 0; $i < count($array2); $i++) {
foreach ($array2[$i] as $key => $value) {
if($key == 'a' && $value == 1){
array_push($array1['data']['ITEM'],
array('SOMETHING' => 'this_is_a',
'ELSE' => "1"
)
);
}
if($key == 'c' && $value == 1){
array_push($array1['data']['ITEM'],
array('SOMETHING' => 'this_is_c',
'ELSE' => "1"
)
);
}
}
echo "Loop #$i result:\n";
var_export($array1);
echo "\n";
}
You can test the above code as a PHP Sandbox snippet.
The actual result is:
Loop #0 result:
array (
'service' => 'coding',
'data' =>
array (
'ITEM' =>
array (
0 =>
array (
'CODE' => '9999',
'QUANTITY' => 1,
),
1 =>
array (
'SOMETHING' => 'this_is_a',
'ELSE' => '1',
),
2 =>
array (
'SOMETHING' => 'this_is_c',
'ELSE' => '1',
),
),
),
)
Loop #1 result:
array (
'service' => 'coding',
'data' =>
array (
'ITEM' =>
array (
0 =>
array (
'CODE' => '9999',
'QUANTITY' => 1,
),
1 =>
array (
'SOMETHING' => 'this_is_a',
'ELSE' => '1',
),
2 =>
array (
'SOMETHING' => 'this_is_c',
'ELSE' => '1',
),
3 =>
array (
'SOMETHING' => 'this_is_a',
'ELSE' => '1',
),
),
),
)
Loop #2 result:
array (
'service' => 'coding',
'data' =>
array (
'ITEM' =>
array (
0 =>
array (
'CODE' => '9999',
'QUANTITY' => 1,
),
1 =>
array (
'SOMETHING' => 'this_is_a',
'ELSE' => '1',
),
2 =>
array (
'SOMETHING' => 'this_is_c',
'ELSE' => '1',
),
3 =>
array (
'SOMETHING' => 'this_is_a',
'ELSE' => '1',
),
4 =>
array (
'SOMETHING' => 'this_is_c',
'ELSE' => '1',
),
),
),
)
The loop #0 result is correct, but the later loops have additional entries in $array1['data']['ITEM']. Desired result:
Loop #0 result:
array (
'service' => coding
'data' => array (
'ITEM' => array (
0 => array (
'CODE' => 9999
'QUANTITY' => 1
)
1 => array (
'SOMETHING' => 'this_is_a'
'ELSE' => 1
)
2 => array (
'SOMETHING' => 'this_is_c'
'ELSE' => 1
)
)
)
)
Loop #1 result:
array (
'service' => coding
'data' => array (
'ITEM' => array (
0 => array (
'CODE' => 9999
'QUANTITY' => 1
)
1 => array (
'SOMETHING' => 'this_is_a'
'ELSE' => 1
)
)
)
)
Loop #2 result:
array (
'service' => coding
'data' => array (
'ITEM' => array (
0 => array (
'CODE' => 9999
'QUANTITY' => 1
)
1 => array (
'SOMETHING' => 'this_is_c'
'ELSE' => 1
)
)
)
)
You may use array_map to loop through the second array and only push to the first array's ['data']['ITEM'] when the current iteration has a key named a and its value is 1.
$arr1 = [
'service' => 'coding',
'data' => [
'ITEM' => [
[
'CODE' => '9999',
'QUANTITY' => 1
]
]
]
];
$arr2 = [
[
'a' => '1',
'b' => '1',
'c' => '1',
'd' => '1',
],
[
'cancel' => '1',
'a' => '1',
'b' => '',
'c' => '',
'd' => '1',
],
[
'cancel' => '1',
'a' => '',
'b' => '1',
'c' => '1',
'd' => '',
],
];
// loop through the second array ($arr2)
// the "use" is very important here as it let's the callback function to access $arr1 variable
$finalArr = array_map(function ($el) use ($arr1) {
// if in the current iteration a kley named "a" and its value is "1" is found then push it to the first array's ['data']['ITEM'] key.
// $arr1 here is passed by value so the real array won't be channged, we're, more or less, working with copy of $arr1 in the function.
isset($el['a']) && $el['a'] == 1 && ($arr1['data']['ITEM'][] = [
'something' => 'This is a', // tried to keep same output as yours
'else' => $el['a'] // tried to keep same output as yours
]);
// for "c" key
isset($el['c']) && $el['c'] == 1 && ($arr1['data']['ITEM'][] = [
'something' => 'This is c', // tried to keep same output as yours
'else' => $el['c'] // tried to keep same output as yours
]);
// return the $arr1 copy regardless of whether we pushed "a" key or not.
return $arr1;
}, $arr2);
// print the resulting array
print_r($finalArr);
Result (for the sample data):
array(
0 => array(
'service' => 'coding',
'data' => array(
'ITEM' => array(
0 => array(
'CODE' => '9999',
'QUANTITY' => 1,
),
1 => array(
'something' => 'This is a',
'else' => '1',
),
2 => array(
'something' => 'This is c',
'else' => '1',
),
),
),
),
1 => array(
'service' => 'coding',
'data' => array(
'ITEM' => array(
0 => array(
'CODE' => '9999',
'QUANTITY' => 1,
),
1 => array(
'something' => 'This is a',
'else' => '1',
),
),
),
),
2 => array(
'service' => 'coding',
'data' => array(
'ITEM' => array(
0 => array(
'CODE' => '9999',
'QUANTITY' => 1,
),
1 => array(
'something' => 'This is c',
'else' => '1',
),
),
),
),
)
You can learn more about callback functions (anonymous functions) in the PHP manual.
You are not returning $array1['data']['ITEM'] to its original state between each iteration. Just write the following between your for() and your foreach().
$array1['data']['ITEM'] = array_slice($array1['data']['ITEM'], 0, 1);
Because array keys must be unique, you don't need to loop through all elements to see if a or c exists -- this will cost unnecessary cycles.
Futhermore, I find array destructuring to be a good choice to isolate the only two values you seek.
I might recommend this much simpler and more intuitive snippet: (Demo)
foreach ($array2 as $i => ['a' => $a, 'c' => $c]) {
$temp = $array1;
if($a == 1) {
$temp['data']['ITEM'][] = [
'SOMETHING' => 'this_is_a',
'ELSE' => '1'
];
}
if ($c == 1) {
$temp['data']['ITEM'][] = [
'SOMETHING' => 'this_is_c',
'ELSE' => '1'
];
}
echo "Loop #$i result:\n";
var_export($temp);
echo "\n";
}
The unexpected entries are present because $array1 is modified with each iteration (specifically, by array_push). To prevent this, each iteration must operate on a different copy of $array1. Since variable assignment and argument passing will each copy an array, either could be used. Similar to argument passing, closures can inherit (note: not in the OOP sense) variables from outer scopes, binding to their values (which will copy an array), providing a third potential basis for a solution.
The fix requiring the least amount of edits is to assign $array1 to another variable at the start of the loop, and replace $array1 in the rest of the loop with this variable:
for ($i = 0; $i < count($array2); $i++) {
$result = $array1;
// ...
Alternatively, by moving the body of the loop to a function, $array1 becomes a copy within the function body:
function process(array $options, array $output) {
// Ensure entries to test are present:
$options += ['a' => NULL, 'c' => NULL];
/* As an alternative to the above, if entries should be added
* to $output whenever 'a' or 'c' has a truthy value,
* `! empty(...)` could be used instead of the `... == 1`
* tests below.
*/
if ($options['a'] == 1) {
$output['data']['ITEM'][] = [
'SOMETHING' => 'this_is_a',
'ELSE' => 1,
];
}
if ($options['c'] == 1) {
$output['data']['ITEM'][] = [
'SOMETHING' => 'this_is_c',
'ELSE' => 1,
];
}
return $output;
}
foreach ($array2 as $i => $subarray) {
echo "// Loop #$i result:";
var_export( process($subarray, $array1) );
echo ";\n";
}
As a third approach, you could apply array_map to $array2, as is done by ths. For comparison, the preceding foreach loop could be replaced with a call to array_map:
var_export(
array_map(function (array $subarray) use ($array1) {
return process($subarray, $array1);
}, $array2)
);
Or, with an arrow function (which automatically use variables from the outer scope):
var_export(
array_map(
fn (array $subarray) => process($subarray, $array1),
$array2
) );
Note that for arrays that won't be modified (or for which modification won't matter), you can pass them by reference (or bind by reference in closures) to avoid the overhead of copying them.
function process(array &$options, array $output) {
// ...
This question already has answers here:
PHP getting sum of values group by key in array [duplicate]
(2 answers)
grouping of array in PHP [duplicate]
(2 answers)
How to sum array value of duplicate data
(5 answers)
Closed 1 year ago.
can someone explain me how to multiply the value from this code? i tried but still cant solve this
arrayK(
0 => array(
'name'=> AA,
'value' => 2.00,
),
1 => array(
'name' => AA,
'value' => 1.82,
),
2 => array(
'name' => BB,
'value' => 2.20,
),
3 => array(
'name' => AA,
'value' => 4.20,
),
4 => array(
'name' => BB,
'value' => 4.20,
),
);
the answer should back to array with value already multiply where it has same name
newArray(
0 => array(
'name'=> AA,
'value' => ...,
),
1 => array(
'name' => BB,
'value' => ....,
),
);
To multiply duplicate value and get new array:
$array=array(
0 => array(
'name'=> AA,
'value' => 2.00,
),
1 => array(
'name' => AA,
'value' => 1.82,
),
2 => array(
'name' => BB,
'value' => 2.20,
),
3 => array(
'name' => AA,
'value' => 4.20,
),
4 => array(
'name' => BB,
'value' => 4.20,
),
);
$result = array();
foreach ($array as $val) {
if (!isset($result[$val['name']]))
$result[$val['name']] = $val;
else
$result[$val['name']]['value'] *= $val['value'];
}
$result = array_values($result); // reindex array
echo "<pre>";
print_r($result);
You can try following solution.
$arrayK = array(
0 => array(
'name'=> "AA",
'value' => 2.00,
),
1 => array(
'name' => "AA",
'value' => 1.82,
),
2 => array(
'name' => "BB",
'value' => 2.20,
),
3 => array(
'name' => "AA",
'value' => 4.20,
),
4 => array(
'name' => "BB",
'value' => 4.20,
),
);
$temp = array_values((array_unique(array_column($arrayK, 'name'))));
$arrayY = [];
for( $i = 0; $i < count($temp); $i++ ) {
foreach( $arrayK as $key => $val ) {
if( $val['name'] == $temp[$i] ) {
$arrayY[$i] = [
'name' => $val['name'],
'value' => isset($arrayY[$i]['value']) ? $val['value'] * $arrayY[$i]['value'] : $val['value']
];
}
}
}
print_r($arrayY);
Out put
Array
(
[0] => Array
(
[name] => AA
[value] => 15.288
)
[1] => Array
(
[name] => BB
[value] => 9.24
)
)
You can play with the code Here
i have a problem with this array, i need get sum form string merge with same key
$data = array(
0 => array(
'name' => 'Alfa Edison, Dwiki',
'budget' => 3700,
),
1 => array(
'name' => 'Maverick Sam',
'budget' => 500,
),
2 => array(
'name' => 'Dwiki',
'budget' => 1000,
),
3 => array(
'name' => 'Steve, Dwiki',
'budget' => 2000,
),
4 => array(
'name' => 'Alfa Edison',
'budget' => 700,
),
5 => array(
'name' => 'Maverick Sam',
'budget' => 4000,
),
6 => array(
'name' => 'Steve, Alfa Edison',
'budget' => 334,
),
);
i want the result this:
array(
0 => array(
'name' => 'Alfa Edison',
'budget' => 4734,
),
1 => array(
'name' => 'Dwiki',
'budget' => 6700,
),
2 => array(
'name' => 'Maverick Sam',
'budget' => 4500,
),
3 => array(
'name' => 'Steve',
'budget' => 2334,
),
);
How to merge String with same Key and Sum the Budget. i try to for each but i'm fail.
i try array_reduce and explode the name but fail.
The problem is that each of the "keys" (names) is really more than one key. So as you iterate the input array you'll need to split those up, then add an inner loop to use the names as keys in the result.
foreach ($data as $item) {
// separate the names
$names = explode(', ', $item['name']);
// iterate the names and set/increase values for them in the result array
foreach ($names as $name) {
$result[$name]['name'] = $name;
$result[$name]['budget'] = $item['budget'] + ($result[$name]['budget'] ?? 0);
}
}
// remove the string keys if necessary
$result = array_values($result);
I have an array:
$initialarray = array(
0 = array(
'unit' => 1,
'class' => 1,
'value' => 'string1'
),
1 = array(
'unit' => 1,
'class' => 2,
'value' => 'string2'
),
2 = array(
'unit' => 1,
'class' => 2,
'value' => 'string3'
),
3 = array(
'unit' => 2,
'class' => 1,
'value' => 'string4'
)
4 = array(
'unit' => 2,
'class' => 2,
'value' => 'string5'
)
);
What would be the best way to structure it (to group the resulting sub-arrays) depending first on the 'unit' field's values, and then depending on the 'class' field's values, like so:
$resultarray = array(
// array of all the sub-arrays of 'unit' = 1
$unit[1] = array(
// array of all the sub-arrays of 'unit' = 1 and 'class' = 1
$class[1] = array(
0 = array(
'unit' => 1,
'class' => 1,
'value' => 'string1'
)
)
// array of all the sub-arrays of 'unit' = 1 and 'class' = 2
$class[2] = array(
0 = array(
'unit' => 1,
'class' => 2,
'value' => 'string2'
),
1 = array(
'unit' => 1,
'class' => 2,
'value' => 'string3'
)
)
)
// array of all the sub-arrays of 'unit' = 2
$unit[2] = array(
// array of all the sub-arrays of 'unit' = 2 and 'class' = 1
$class[1] = array(
0 = array(
'unit' => 2,
'class' => 1,
'value' => 'string4'
)
)
// array of all the sub-arrays of 'unit' = 2 and 'class' = 2
$class[2] = array(
0 = array(
'unit' => 2,
'class' => 2,
'value' => 'string5'
)
)
)
)
I have asked a similar question here and got a working answer for only one iteration, i.e. for only structuring the array by one of the fields. But I could not make the same solution work for multiple iterations, i.e. for more than one field.
Also, is there a solution to structure a multidimensional array depending on more than two fields?
I think it's not a way of asking the question. It is very simple , you can do this by playing with arrays,keys and etc.... So first you should try hard for the problem. After If you have any problem in the middle of your tries then you can ask that here. I have solved your problem here is the complete code , but next time please do some work and then only post the problem. Never ask for the code.
foreach ($initialarray as $key1=>$val1)
{
foreach ($val1 as $key2=>$val2)
{
if($key2=='unit')
{
$num=$val2;
if($val2!=$num)
$testarr['unit'.$val2]=array();
}
if($key2=='class')
{
$testarr['unit'.$num]['class'.$val2][]=$val1;
}
}
}
print_r($testarr);
I must offer a better way for you and future researchers...
You only need one loop, and you merely need to nominate the result array's key values before using [] to "push" new data into the deepest subarray.
*there is absolutely no need for any condition statements or a second loop.
Code: (Demo)
$initialarray = [
['unit' => 1, 'class' => 1, 'value' => 'string1'],
['unit' => 1, 'class' => 2, 'value' => 'string2'],
['unit' => 1, 'class' => 2, 'value' => 'string3'],
['unit' => 2, 'class' => 1, 'value' => 'string4'],
['unit' => 2, 'class' => 2, 'value' => 'string5']
];
foreach ($initialarray as $row) {
$result[$row['unit']][$row['class']][] = $row;
}
var_export($result);
Output:
array (
1 =>
array (
1 =>
array (
0 =>
array (
'unit' => 1,
'class' => 1,
'value' => 'string1',
),
),
2 =>
array (
0 =>
array (
'unit' => 1,
'class' => 2,
'value' => 'string2',
),
1 =>
array (
'unit' => 1,
'class' => 2,
'value' => 'string3',
),
),
),
2 =>
array (
1 =>
array (
0 =>
array (
'unit' => 2,
'class' => 1,
'value' => 'string4',
),
),
2 =>
array (
0 =>
array (
'unit' => 2,
'class' => 2,
'value' => 'string5',
),
),
),
)
If I may express myself in the following manner: I only see the front-end of your problem and know nothing about its back-end, e.g. "Where does the data come from?", "How is it collected and stored", etc. so my answer might not be a real help but still I'll give my "tuppence".
If you can store all that data in a relational database (in form of table(s)) it would be much more easier and faster(!) to select the needed data from the database instead of rearranging arrays, which will take some more time in comparison.
Just as an example you might then select (and store it into an array) all items which have unit = '1' and / or all items which have class = '2'. That would make life much more easier IMHO, than having all the data in a multidimensional array and then try to sort it / rearrange it. Especially if you do that based on more than one property.
I have two arrays of products, both formatted exactly the same, like so:
$products = array(
[0] => array(
['product_id'] => 33
['variation_id'] => 0
['product_price'] => 500.00
),
[1] => array(
['product_id'] => 48
['variation_id'] => 0
['product_price'] => 600.00
),
)
I would like to be able to return a list of only those products not found in the second array, based on the product ID.
I only care about those NOT found in the second array, not additional ones added to the first, so array_diff won't seem to do the trick.
I suspect you want something like array_udiff. This lets you specify how to compare the two arrays, using a callback function. You just create a callback that compares based on product id's.
I think this satisfies what you want because the array_diff family of functions only compare the first array to the rest, it does not return elements that array2 (or 3, or 4) have that array1 does not.
<?php
$products = array(
0 => array(
'product_id' => 33,
'variation_id' => 0,
'product_price' => 500.00
),
1 => array(
'product_id' => 48,
'variation_id' => 0,
'product_price' => 600.00
)
);
$products2 = array(
1 => array(
'product_id' => 48,
'variation_id' => 0,
'product_price' => 600.00
),
2 => array(
'product_id' => 49,
'variation_id' => 0,
'product_price' => 600.00
)
);
function compare_ids($a, $b)
{
return $b['product_id'] - $a['product_id'];
}
var_dump(array_udiff($products, $products2, "compare_ids"));
?>
Outputs:
array(1) {
[0]=>
array(3) {
["product_id"]=>
int(33)
["variation_id"]=>
int(0)
["product_price"]=>
float(500)
}
}
A simple foreach loop should be enough:
<?php
$products = array(
0 => array(
'product_id' => 33,
'variation_id' => 0,
'product_price' => 500.00
),
1 => array(
'product_id' => 48,
'variation_id' => 0,
'product_price' => 600.00
)
);
$products2 = array(
1 => array(
'product_id' => 48,
'variation_id' => 0,
'product_price' => 600.00
),
2 => array(
'product_id' => 49,
'variation_id' => 0,
'product_price' => 600.00
)
);
$diff = array();
// Loop through all elements of the first array
foreach($products2 as $value)
{
// Loop through all elements of the second loop
// If any matches to the current element are found,
// they skip that element
foreach($products as $value2)
{
if($value['product_id'] == $value2['product_id'])
continue 2;
}
// If no matches were found, append it to $diff
$diff[] = $value;
}
The $diff array would then only hold the following value:
array (
0 =>
array (
'product_id' => 49,
'variation_id' => 0,
'product_price' => 600,
),
)
Hope this helped!