I would like to switch from array 1 to array 2 according to the model below
I'm stuck on the implementation of item averages
the lessons, the number of notes and the order of the notes are random
Array 1
$tabAsso =
Array
(
[51] => Array
(
[id] => 51
[name] => JOHN
[studies] => Array
(
[0] => math
[1] => LV1
[2] => math
[3] => LV1
[4] => history
[5] => history
)
[notesC] => Array
(
[0] => 12
[1] => 18
[2] => 28
[3] => 45
[4] => 10
[5] => 18
)
[denumsC] => Array
(
[0] => 15
[1] => 60
[2] => 40
[3] => 75
[4] => 12
[5] => 45
)
)
[52] => Array
(
[id] => 52
[name] => PETER
[studies] => Array
(
[0] => sport
[1] => tech
[2] => sport
...
For example for the math average, you must read :
notesC:
sum (12 + 28)
denumC
sum (15 +40)
then average : (40/55) *20 = 14.5
I would like to reach this array 2
[51] => Array
(
[id] => 51
[name] => JOHN
[studies] => Array
(
[0] => math
[1] => LV1
[2] => history
)
[averages] => Array
(
[0] => 14.5
[1] => 9.3
[2] => 9.8
)
)
[52] => Array
(
[id] => 52
[name] => PETER
[studies] => Array
(
[0] => sport
[1] => tech
)
[averages] => Array
(
[0] => xx
[1] => xx
)
)
...
So far I have managed to do this ...
$tabAssoForBar = [];
foreach ($tabAsso as $id => $t) {
foreach ($t['studies'] as $k => $m) {
if (!array_key_exists($id, $tabAssoForBar)) {
$tabAssoForBar[$id] = [
'id' => $id,
'name' => $t['name'],
];
$tabAssoForBar[$id]['studies'] = [$m];
} else {
if (!in_array($m, $tabAssoForBar[$id]['studies'])) {
$tabAssoForBar[$id]['studies'][] = $m;
} else {
// nothing
}
}
}
};
I return studies with only 3 fields (math, LV1, history) but cannot create the averages field
Thanks for your help
You might use an approach to get all the indices from
"study" for a all the unique values, and get the values from "notesC" and "denumsC" for those corresponding indices.
Then per unique value for "study", first sum them separately for "notesC" and "denumsC" and then divide those results and multiply the outcome by 20 to fulfill this formula:
(40/55) *20 = 14.5
You can create the result array by using the current index as the index in the new array and the unique studies and averages to it.
For example
$tabAssoForBar = [];
foreach ($tabAsso as $id => $t) {
$uniqueStudies = array_unique($t['studies']);
$averages = [];
foreach ($uniqueStudies as $uniqueStudy) {
$keysFromStudies = array_keys(array_filter($t['studies'], function($x) use ($uniqueStudy) {
return $x === $uniqueStudy;
}));
$averages[] = round(
(
array_sum(array_intersect_key($t['notesC'], array_flip($keysFromStudies))) /
array_sum(array_intersect_key($t['denumsC'], array_flip($keysFromStudies)))
) * 20,
1
);
}
$tabAssoForBar[$id] = [
'id' => $t['id'],
'name' => $t['name'],
'studies' => array_values($uniqueStudies),
'averages' => $averages
];
}
print_r($tabAssoForBar);
Output
Array
(
[51] => Array
(
[id] => 51
[name] => JOHN
[studies] => Array
(
[0] => math
[1] => LV1
[2] => history
)
[averages] => Array
(
[0] => 14.5
[1] => 9.3
[2] => 9.8
)
)
)
See a php demo
Following is my array
(
[0] => Array
(
[items] => 10.4
[Total] => 10.4
)
[1] => Array
(
[items] => 10.5
[Total] => 10.5
)
[2] => Array
(
[items] => 4.5
[Total] => 15
)
[3] => Array
(
[items] => 15.2
[Total] => 15.2
)
[4] => Array
(
[items] => 8.4
[Total] => 8.4
)
)
Here each array has items & total , I want to check if total of each item is less then 20 then set items with total in a array and also not check already checked item.
For example there are 4 items in array 0 has item 10.4 & total 10.4 then check is less then 20 if not then plus second array item means (10.4 + 10.5) again check if is greater then 20 If yes then set last checked in array like array('item'=>10.4, 'total'=>10.4) , Now second time 10.4 item will skip & check with 10.5 + 4.5 etc...
I want output like.
(
[0] => Array
(
[items] => array([0]=>10.4),
[Total] => 10.4
)
[1] => Array
(
[items] => array(
[0] => 10.5,
[1] => 4.5
),
[Total] => 15
)
[2] => Array
(
[items] => array([0]=>15.2)
[Total] => 15.2
)
[3] => Array
(
[items] => array([0]=>8.4)
[Total] => 8.4
)
)
Following is my script.
$packageInfo = $ordercon->get_package_items_by_order_number($order_number); // Comes from model
// First calculate the total
foreach ($packageInfo as $key => $package) {
$packageInfo[$key]['total_weight'] = $package['quantity'] * $package['weight'];
$packageInfo[$key]['currnt_item'] = $package['quantity'] * $package['weight'];
}
// Then check count the packages ?
$packages = [];
$packageTotalWeight = 0;
$packageItemWeight = 0;
foreach ($packageInfo as $key => $package) {
if(($packageTotalWeight + $package['total_weight']) > 20){
$packages[]['final_total'] = $packageTotalWeight;
$packageTotalWeight = $package['total_weight'];
$data[] = array('items'=>$package['currnt_item'], 'Total'=>$packageTotalWeight); // For combine items
} else {
$packages[]['currntItem'] = $package['quantity'] * $package['weight'];
$packageTotalWeight += $package['total_weight'];
$data[] = array('items'=>$package['currnt_item'], 'Total'=>$packageTotalWeight);
}
}
echo "<pre>";print_r($data);
echo '<pre>packageInfo';print_r($packageInfo);
Let's say I have this set of arrays as input:
[
0 => [1,2,4,5],
1 => [2,3,4],
2 => [1,3],
]
I would like to find all permutations possible selecting one value from each array. That value would be unique in the final result, so it won't repeat. For example, I can't have 1 twice in the result.
The count of arrays on input is the same as count of arrays on output.
Examples of combinations wanted (key=>value):
[0 => 1,1 => 2,2 => 3]
[0 => 2,1 => 3,2 => 1]
[0 => 5,1 => 2,2 => 1]
[0 => 1,1 => 3,2 => null]
Wrong results
[0 => 1,1 => 2,2 => 1]
or
[0 => 2,1 => 2,2 => 3]
I would like to get set of all possible permutations using PHP. How can I do that?
I have attached real data set http://pastebin.com/U6Hyawm4 However, I have no idea how many permutations there may be.
Here's a non-recursive version that's also optimized
/**
* Generates all the possible unique N-tuples from an array of N arrays of integers
*
* #param array $input
* #return array
*/
function generateCombinations(array &$input) {
// since the example results included [1, 3, null] I have assumed that
// null is a possible value of each set.
$sets = [];
foreach($input as $set) {
if(!in_array(null, $set)) {
$set[] = null;
}
$sets[] = $set;
}
// by working on the iterators of each array this loop
// linearizes the entire set of possible combinations
// and iterates it (skipping as many as it can).
$output = [];
$setCount = count($sets);
while(current($sets[0]) !== false) {
$testCombo = [];
for($setIdx = 0; $setIdx < $setCount; $setIdx++) {
if(!in_array(current($sets[$setIdx]), $testCombo)) {
$testCombo[] = current($sets[$setIdx]);
}
else {
// when a combination is thrown out as duplicate
// iterate to skip any other combo's that would also
// contain that duplicate
iterateSets($sets, $setIdx);
break;
}
}
// if there were no duplicates add it to the output and iterate
if(count($testCombo) == $setCount) {
$output[] = $testCombo;
iterateSets($sets, $setCount - 1);
}
}
return $output;
}
/**
* Iterates to the next potentially valid combination. I think of
* this like doing long-hand addition. Add 1 and carry is akin to
* next and reset.
*
* #param array $sets
* #param $index
*/
function iterateSets(array &$sets, $index) {
// reset iterators of all sets past the current one to skip
// combos that cannot be valid
for($i = $index + 1, $ic = count($sets); $i < $ic; $i++) {
reset($sets[$i]);
}
// always move one on current set
next($sets[$index]);
while($index > 0 && current($sets[$index]) === false) {
// wrap if current set is at the end
reset($sets[$index]);
$index--;
// move one for the preceding set
next($sets[$index]);
// then repeat
}
}
The resulting array is:
[
[1,2,3]
[1,2,null]
[1,3,null]
[1,4,3]
[1,4,null]
[1,null,3]
[2,3,1]
[2,3,null]
[2,4,1]
[2,4,3]
[2,4,null]
[2,null,1]
[2,null,3]
[4,2,1]
[4,2,3]
[4,2,null]
[4,3,1]
[4,3,null]
[4,null,1]
[4,null,3]
[5,2,1]
[5,2,3]
[5,2,null]
[5,3,1]
[5,3,null]
[5,4,1]
[5,4,3]
[5,4,null]
[5,null,1]
[5,null,3]
[null,2,1]
[null,2,3]
[null,3,1]
[null,4,1]
[null,4,3]
]
Here's an inefficient version:
$input = array(
[1,2,4,5],
[2,3,4],
[1,3]
);
function appendUnique($subs, $i) {
global $input;
if ($i == count($input)) {
return $subs;
}
$output = array();
foreach ($subs as $sub) {
foreach ($input[$i] as $v) {
$new_sub = array_values($sub);
if (in_array($v, $sub)) {
$new_sub[] = null;
} else {
$new_sub[] = $v;
}
$output[] = $new_sub;
}
}
return appendUnique($output, $i+1);
}
$output = appendUnique([[]], 0);
$output_json = array();
foreach ($output as $row) {
$output_json[] = json_encode($row);
}
$output_json = array_unique($output_json);
$deduped = array();
foreach ($output_json as $json) {
$deduped[] = json_decode($json);
}
print_r($deduped);
outputs:
Array
(
[0] => Array
(
[0] => 1
[1] => 2
[2] =>
)
[1] => Array
(
[0] => 1
[1] => 2
[2] => 3
)
[2] => Array
(
[0] => 1
[1] => 3
[2] =>
)
[3] => Array
(
[0] => 1
[1] => 4
[2] =>
)
[4] => Array
(
[0] => 1
[1] => 4
[2] => 3
)
[5] => Array
(
[0] => 2
[1] =>
[2] => 1
)
[6] => Array
(
[0] => 2
[1] =>
[2] => 3
)
[7] => Array
(
[0] => 2
[1] => 3
[2] => 1
)
[8] => Array
(
[0] => 2
[1] => 3
[2] =>
)
[9] => Array
(
[0] => 2
[1] => 4
[2] => 1
)
[10] => Array
(
[0] => 2
[1] => 4
[2] => 3
)
[11] => Array
(
[0] => 4
[1] => 2
[2] => 1
)
[12] => Array
(
[0] => 4
[1] => 2
[2] => 3
)
[13] => Array
(
[0] => 4
[1] => 3
[2] => 1
)
[14] => Array
(
[0] => 4
[1] => 3
[2] =>
)
[15] => Array
(
[0] => 4
[1] =>
[2] => 1
)
[16] => Array
(
[0] => 4
[1] =>
[2] => 3
)
[17] => Array
(
[0] => 5
[1] => 2
[2] => 1
)
[18] => Array
(
[0] => 5
[1] => 2
[2] => 3
)
[19] => Array
(
[0] => 5
[1] => 3
[2] => 1
)
[20] => Array
(
[0] => 5
[1] => 3
[2] =>
)
[21] => Array
(
[0] => 5
[1] => 4
[2] => 1
)
[22] => Array
(
[0] => 5
[1] => 4
[2] => 3
)
)
I have an array with nested array in it like below.
cart (
[total] => 98
[itemcount] => 3
[items] => Array ( [0] => 0 [1] => 3 [2] => 5 )
[itemprices] => Array ( [0] => 33.00 [3] => 32.00 [5] => 33 )
[itemqtys] => Array ( [0] => 1 [3] => 1 [5] => 1 )
[iteminfo] => Array ( [0] => Chemistry [3] => Additional Mathematics [5] => Physics )
)
And I have the code below in a switch when the user enter correct discount code, this function will trigger. I can get it work to display the discounted price.
$anewvalue = 16.50;
$physubject = "Physics";
$index = array_search($physubject , $cart->iteminfo);
if (false !== $index) {
$cart->itemprices[$index] = $anewvalue;}
Problem is that how do I update the total whenever the user key in a correct discount code and submit the form, so that the total price will always up to date, because now it doesn't do that.
You need to recalculate the total every time a correct discount is applied.
if (false !== $index) {
$cart->itemprices[$index] = $anewvalue;
//re-calculate the total
$total = 0;
foreach ($cart->itemprices as $key=>$itemprice) {
$total += $itemprice * $cart->itemqtys[$key];
}
$cart->total = $total
}
I am having some difficulty looping through an array and calculating fields. Here is the array $iroom:
Array
(
[num_rooms] => 2
[adults] => Array
(
[0] => 2
[1] => 2
)
[prices] => Array
(
[0] => 44.5
[1] => 44.5
)
[roomTotalPrice] => Array
(
[0] => 89
[1] => 89
)
[price] => 178
)
I want to (adults*prices)+(adults*$asup)+(chidern*$csup)+$ssup and pu the answer into the roomTotalPrice. So far the outer forloop sets the roomTotalPrice price but I cannot get the inner loops to calculate the price. The $sup are extra supplement prices.
The code I got so far:
foreach($iroom['roomTotalPrice'] as &$irt){
foreach($iroom['adults'] as $ira){
}
$irt = ;
}
CODE WRAPPED IN FUNCTION, TO HANDLE NEW ARRAY FORMAT
/*
Note that this function may not be 100% correct. I notice you have removed
the 'supp' key from the array, and that your current spec doesn't do anything
with the 'price' key. I suspect you may want the line
+ ((isset($array['supp'])) ? $array['supp'] : 0);
to read
+ ((isset($array['price'])) ? $array['price'] : 0);
*/
function calculateTotalPrices ($array, $asup = 10, $csup = 10) {
if (!is_array($array) || !isset($array['num_rooms']) || !$array['num_rooms']) return FALSE; // make sure data is valid
for ($i = 0; $i < $array['num_rooms']; $i++) { // Loop num_rooms times
$array['roomTotalPrice'][$i] =
((isset($array['adults'][$i],$array['prices'][$i])) ? ($array['adults'][$i] * $array['prices'][$i]) + ($array['adults'][$i] * $asup) : 0) // Calculate price for adults
+ ((isset($array['childern'][$i])) ? ($array['childern'][$i] * $csup) : 0) // Calculate price for children
+ ((isset($array['supp'])) ? $array['supp'] : 0); // Add the supplement
}
// Get a total price for adults + children + supplements for all rooms
$array['grandTotal'] = array_sum($array['roomTotalPrice']);
return $array;
}
$iroom = array (
'num_rooms' => 2,
'adults' => array (
0 => 2,
1 => 3
),
'childern' => array (
0 => 1,
1 => 2
),
'prices' => array (
0 => 44.5,
1 => 44.5
),
'price' => 178,
);
print_r(calculateTotalPrices($iroom));
/* With the above array, outputs
Array
(
[num_rooms] => 2
[adults] => Array
(
[0] => 2
[1] => 3
)
[childern] => Array
(
[0] => 1
[1] => 2
)
[prices] => Array
(
[0] => 44.5
[1] => 44.5
)
[price] => 178
[roomTotalPrice] => Array
(
[0] => 119
[1] => 183.5
)
[grandTotal] => 302.5
)
*/
print_r(calculateTotalPrices($iroom,20,25));
/* With your sample array, outputs
Array
(
[num_rooms] => 2
[adults] => Array
(
[0] => 2
[1] => 3
)
[childern] => Array
(
[0] => 1
[1] => 2
)
[prices] => Array
(
[0] => 44.5
[1] => 44.5
)
[price] => 178
[roomTotalPrice] => Array
(
[0] => 154
[1] => 243.5
)
[grandTotal] => 397.5
)
*/
CODE UPDATED WITH ADDITIONAL CHECKS
foreach ($iroom as $k1 => $v1) { // Loop outer array
if (is_array($v1)) { // Make sure element is an array
foreach ($v1 as $k2 => $v2) { // Loop inner array
if (is_array($v2)) { // Make sure element is an array
for ($i = 0; $i < $v2['num_rooms']; $i++) { // Loop num_rooms times
$iroom[$k1][$k2]['roomTotalPrice'][$i] =
((isset($v2['adults'][$i],$v2['prices'][$i])) ? ($v2['adults'][$i] * $v2['prices'][$i]) + ($v2['adults'][$i] * $asup) : 0) // Calculate price for adults
+ ((isset($v2['childern'][$i])) ? ($v2['childern'][$i] * $csup) : 0) // Calculate price for children
+ $v2['supp']; // Add the supplement
}
// Get a total price for adults + children + supplements for all rooms
$iroom[$k1][$k2]['grandTotal'] = array_sum($iroom[$k1][$k2]['roomTotalPrice']);
}
}
}
}
print_r($iroom);
EDIT
Using the exact code above, feeding in the array above, and setting $asup = $csup = 10; at the top, I get no errors, and this output:
Array
(
[10] => Array
(
[12] => Array
(
[num_rooms] => 2
[adults] => Array
(
[0] => 2
[1] => 3
)
[childern] => Array
(
[0] => 1
[1] => 2
)
[prices] => Array
(
[0] => 44.5
[1] => 44.5
)
[price] => 178
[supp] => 0
[roomTotalPrice] => Array
(
[0] => 119
[1] => 183.5
)
[grandTotal] => 302.5
)
)
)
Note that the first result comes out at 119, not 129 as you state in the comment above - this is because in your example array, supp is 0 and not 10, as you have used in your calculation.
I have also tested with more complex arrays (with more elements at the first and second levels) and it works fine.
I'm guessing if you are getting "invalid argument supplied for foreach" errors it's because in your actual array, you highest level has some non-array memebers. This can easily be overcome by changing
foreach ($v1 as $k2 => $v2) {
to
if (is_array($v1)) foreach ($v1 as $k2 => $v2) {