There may be a better way to state the question, but I'm workin' with what I know.
On Woocommerce I'm trying to get the _wc_rating_count for each star (1-5), but also for two products; then I want to combine theme; e.g., I am merging the reviews of two products on one page, in one graph.
I am doing that this way:
$product_id = array( 2146, 2166 );
$ratings = array(5, 4, 3, 2, 1);
foreach ($product_id as $pid) :
$product = wc_get_product($pid);
foreach ($ratings as $rating) :
$rating_count = $product->get_rating_count($rating);
$percentage = ($rating_count / $count) * 100 . "%";
//echo $rating_count . '<br/>';
endforeach;
endforeach;
The problem is, I'm getting an array of 10 items (2 products x 5 star ratings( 5,4,3,2,1), and I need those values merged.
11
1
0
0
2
8
0
0
0
1
Where I need it to be
19
1
0
0
3
Do you know how I may get two arrays out of the embedded foreachs and merge them based on the $ratings array?
Thanks for your help :)
So here is what do you like to achieve:
$product_ids = array( 2146, 2166 );
$ratings = array(5, 4, 3, 2, 1);
$rate_countings = array();
foreach ($product_ids as $pid){
$product = wc_get_product($pid);
foreach ($ratings as $rating){
$rating_count = $product->get_rating_count($rating);
//$percentage = ($rating_count / $count) * 100 . "%";
if( !isset($rate_countings[$rating]) ){
$rate_countings[$rating] = 0;
}
$rate_countings[$rating] += $rating_count;
}
}
var_dump($rate_countings);
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I have one array and i want to multiply like 106 multiply by 76 but i want to multiply in this pattern it is not giving proper result
1 0 6
6 7
_____________
7 4 2
6 3 6 x
_________________
7 1 0 2
The code is running properly but there is mistake in the addition i guess the output of the code is 424991 It should be 7102
<?php
$data=array(
'digit1' => 1,
'digit2' => 0,
'digit3' => 6,
'digit4' => 6,
'digit5' => 7 );
$a=$data['digit1']*$data['digit4'];
$b=$data['digit2']*$data['digit4'];
$b1=$data['digit3']*$data['digit4'];
$c=$data['digit1']*$data['digit5'];
$d=$data['digit2']*$data['digit5'];
$d1=$data['digit3']*$data['digit5'];
$e=$b+$a+$b1;
echo $e;
$f=$c+$d+$d1;
echo $f;
echo $e+$f;
?>
By using floor and modulus, you should be able to solve your problem.
Try this updated code.
$data = array(
'digit1' => 1,
'digit2' => 0,
'digit3' => 6,
'digit4' => 6,
'digit5' => 7
);
# ------------------------------------------------------------
$product = $data['digit5'] * $data['digit3'];
$a = $product % 10;
$carry = floor($product / 10);
$product = ($data['digit5'] * $data['digit2']) + $carry;
$b = $product % 10;
$carry = floor($product / 10);
$product = ($data['digit5'] * $data['digit1']) + $carry;
$c = $product;
#-------------------------------------------------------------
$product = $data['digit4'] * $data['digit3'];
$d = $product % 10;
$carry = floor($product / 10);
$product = ($data['digit4'] * $data['digit2']) + $carry;
$e = $product % 10;
$carry = floor($product / 10);
$product = ($data['digit4'] * $data['digit1']) + $carry;
$f = $product;
#-------------------------------------------------------------
$x = intval($c . $b . $a);
$y = intval($f . $e . $d) * 10;
#-------------------------------------------------------------
echo sprintf("%' 10d\n", $c.$b.$a);
echo sprintf("%' 9d\n", $f.$e.$d);
echo "----------\n";
echo sprintf("%' 10d\n", $x + $y);
You can thank me later for doing your assignment for you.
In your program, you do not take into account the placevalues.
For example, when you multiply $data['digit1'] by $data['digit4'], you should be multiplying 100 by 60, but you are instead multiplying 1 by 6.
And the reason you have a larger number (6 digits) is because you're echoing two values.
This is what your program is doing (step by step):
$data = array(
'digit1' => 1,
'digit2' => 0,
'digit3' => 6,
'digit4' => 6,
'digit5' => 7
);
$a=$data['digit1']*$data['digit4']; // $a = 6
$b=$data['digit2']*$data['digit4']; // $b = 0
$b1=$data['digit3']*$data['digit4']; // $b1 = 36
$c=$data['digit1']*$data['digit5']; // $c = 7
$d=$data['digit2']*$data['digit5']; // $d = 0
$d1=$data['digit3']*$data['digit5']; // $d1 = 42
$e=$b+$a+$b1; // $e = 42
echo $e; // OUTPUT 42
$f=$c+$d+$d1; // $f = 49
echo $f; // OUTPUT 42
echo $e+$f; // OUTPUT 91
This is creating your output 424991.
If you wanted to get your program to work as-is (instead of using a dynamic program like below), then the following should work:
$data = array(
'digit1' => 1,
'digit2' => 0,
'digit3' => 6,
'digit4' => 6,
'digit5' => 7
);
$a=$data['digit1']*100*$data['digit4']*10;
$b=$data['digit2']*10*$data['digit4']*10;
$b1=$data['digit3']*1*$data['digit4']*10;
$c=$data['digit1']*100*$data['digit5']*1;
$d=$data['digit2']*10*$data['digit5']*1;
$d1=$data['digit3']*1*$data['digit5']*1;
$e=$b+$a+$b1;
$f=$c+$d+$d1;
echo $e+$f;
Your code is a bit too rigid, so may I suggest a more dynamic version?
Given any two numeric strings in PHP:
$num1 = "106";
$num2 = "67";
You can split each one into arrays of numbers:
$num1Split = str_split($num1);
$num2Split = str_split($num2);
And then multiply it out:
$total = 0;
for($i = 0; $i < count($num1Split); $i++)
for($j = 0; $j < count($num2Split); $j++)
$total += $num1Split[$i]*pow(10,count($num1Split)-$i-1) * $num2Split[$j]*pow(10,count($num2Split)-$j-1);
echo $total;
I want to display 10 highest figure and 10 lowest figure in a multi-dimensional array.
I have figured out way to display the maximum figure using max(), but when I use min(), the least less value get looped again and again for 10 times e.g 2.
How can I reuse my code to display minimum value in my array?
$totalCustomer = count($customerArray);
$postion = 0;
foreach ($customerArray as $custom) {
$postion = $postion + 1;
if($totalCustomer - $postion < 9){
$top[] = $custom['spend'];
$maxprice = max($top);
echo "Max spend price is ". $maxprice. "<br>";
}
}
#hek2mgl answer is a good one. But you can take advantage of PHP array's indexes to avoid sorting and gaining performance.
$prices = [];
foreach ( $customerArray as $custom )
{
// This approach uses your price as an ordering index, and supposes two decimal points
$index = intval( $custom['spend'] * 100 );
$prices[$index] = $custom['spend'];
}
// Showing lowest 10 prices
$top = array_slice( $prices, 0, 10 );
// Showing top 10 prices
$low = array_slice( array_reverse( $prices ), 0, 10 );
I would use usort:
/* Sort the array the value of 'spend' */
usort($customerArray, function($a, $b) {
if($a['spend'] == $b['spend']) {
return 0;
} else if ($a['spend'] > $b['spend']) {
return -1;
} else {
return 1;
}
});
/* The top 10 elements are now on top of the array */
$top = array_slice($customerArray, 0, 10);
/* If we reverse the array using array_reverse() the
smallest items are on top */
$low = array_slice(array_reverse($customerArray), 0, 10);
I've got a problem which takes up a lot of time. While it's supposed to be really easy (because it's just so simple!).
My problem:
I have these values inside two arraylists:
$row[0]->COUNTER1 20 10 15
$row[0]->GRADE_POINTS 0 3 5
I am supposed to change these arraylists into this example:
$row[0]->COUNTER1 20 0 0 10 0 15
$row[0]->GRADE_POINTS 0 1 2 3 4 5
So the missing values are supposed to have 0 as the counter.
While this isn't that hard to do it I'm probably over thinking it.
The code which I use to create the first set of numbers is:
$result = new SimpleXMLElement($xmlresult);
$xml = $result->children("soapenv", true)->Body->children();
$xmlBody = $xml[0];
$countPerResultaat = array();
foreach($xmlBody->query[0] as $row)
{
$countPerResultaat[] = (int) $row[0]->COUNTER1;
$xaxis[] = (string) $row[0]->GRADE_POINTS;
}
The code I though that would work is this:
for($i; $i<=10; $i++){
//foreach($xmlBody->query[0] as $row)
//{
$row = $xmlBody->query[0];
if($i==$row[0]->GRADE_POINTS){
$countPerResultaat[] = (int) $row[0]->COUNTER1;
$xaxis[] = (string) $row[0]->GRADE_POINTS;
}else{
$xaxis[] = (string) $i;
$countPerResultaat[] = (int) 0;
}
}
But the row can't be used, I really don't know how to fix this. My only solution would be to use another for-loop, which would create 100 values probably.
Thanks for helping in advance!
If I understand correctly and if $row[0]->COUNTER1 and $row[0]->GRADE_POINTS are arrays. You will just need to loop them and use in_array(). Consider this example:
$counter1 = array(20, 10, 15);
$grade_points = array(0, 3, 5);
$new_grade_points = range(min($grade_points), max($grade_points));
foreach($new_grade_points as $key => &$value) {
// check if its part of the missing index if not get the value,
// if its the missing index put 0
$value = (in_array($key, $grade_points)) ? array_shift($counter1) : 0;
}
$counter1 = array_values($new_grade_points); // now contains 20,0,0,10,0,15
$grade_points = array_keys($new_grade_points); // now contains 0,1,2,3,4,5
print_r($counter1);
Sample Output:
Array
(
[0] => 20
[1] => 0
[2] => 0
[3] => 10
[4] => 0
[5] => 15
)
I think you want to count the amount of times a grade has been given? You should just loop through as usual, and when there is no value you should/could define it as 0. After that just count how many duplicates you have in the array. That way the key of the $xaxis is the grade, and the value is the amount of times that grade has been given.
foreach($xmlBody->query[0] as $row)
{
$counter = (int) $row[0]->COUNTER1;
if(counter) $countPerResultaat[] = $counter;
else $countPerResultaat[] = 0;
}
$xaxis = array_count_values($counter);
The user requests a Product Category and says what quantity they want of it, ie Sugar 7 lbs.
In the search results, from the database, I have the following items (which are each different products):
Sugar, 8 oz .75
Sugar, 1 lb 1.50
Sugar, 2 lb 4.00
Sugar, 5 lb 7.00
Sugar, 10 lb 11.00
Current process:
Get the search results
Check for the cheapest option for any one of the results (only 10 lbs would meet it) or multiples of one of the results (however many of 1 needed to match the criteria, so 7 X 1 lb)
Put the individual product ids into an array
Get the 1:1 permutations, but within that, use some code to add in up to 3 repeats (because 5 lbs + 2 X 1 lbs is the cheapest option, not 5 lbs + 2 lbs)
In this, check for different quantity unit (oz vs lb) and be able to convert and compare
Compare for cheapest and return cheapest
I'm even disregarding where there are more than 6 elements in the permutation to weed out unlikely options and reduce overhead
This works FINE unless there are > 9 product ids (for some I have > 25), then I get this error in the logs (and a completely unrelated error in the browser): Premature end of script headers
This is a lot of code. I'm sorry, just want to be thorough! Is there a more efficient/effective way?
function processCombos($arr, $qty_search, $qty_unit_search){ //$arr is the dataset, $qty_search is 7, $qty_unit_search is 1 for lbs
$combo=array();
$pid_arr = arrayifyProductIDs($arr);
$count = count($pid_arr);
$members = pow(2,$count);
for ($i = 0; $i < $members; $i++) {
$b = sprintf("%0".$count."b",$i);
$out = array();
for ($j = 0; $j < $count; $j++) {
if ($b{$j} == '1'){
$out[] = $pid_arr[$j];
}
}
$minLength=2;
$out_max = count($out);
if ($out_max >= $minLength) {
// now add in different repeats of each of them
$repeat_max = 3;
$indiv = array();
for($k=0;$k<$out_max;$k++){
$tmp = array();
for ($r = 0; $r < $repeat_max; $r++) $tmp[$r] = array_fill(0, $r + 1, $out[$k]);
$indiv[] = $tmp;
}
$x_ct = count($indiv[0]);
$y_ct = count($indiv[1]);
$z_ct = count($indiv[2]) > 0 ? count($indiv[2]): 0;
$perm = array();
for($x=0;$x<$x_ct;$x++){
for($y=0;$y<$y_ct;$y++){
if($z_ct > 0){
for($z=0;$z<$z_ct;$z++){
$perm = array_merge($indiv[0][$x],$indiv[1][$y],$indiv[2][$z]);
}
}else{
$perm = array_merge($indiv[0][$x],$indiv[1][$y]);
}
$p=0;
$max_p=count($perm);
if($max_p >=7){
}else{
$product_ids = array();
$qty = 0;
$price = 0;
while($p < $max_p){
$product_id = $perm[$p];
$data = $arr[$product_id];
if(!$data['qty_unit_id'] OR !$data['qty']){continue;} // go to the next one if it doens't have qty or qty_unit
if($data['qty_unit_id'] == $qty_unit_search){
$product_ids[] = $product_id;
$qty += $data['qty'];
$price += $data['price'];
}else{
$unit_to_convert_data = getQtyUnitName($qty_unit_search);
$unit_to_convert = $unit_to_convert_data['abbr'];
$unit_to_convert_type = $unit_to_convert_data['conv_file'];
if($unit_to_convert_type == $data['conv_file']){
if($data['conv_file'] == "Mass"){
$product_conv = new PhpUnitsOfMeasure\PhysicalQuantity\Mass($data['qty'], $data['qty_unit']);
}else{
$product_conv = new PhpUnitsOfMeasure\PhysicalQuantity\Volume($data['qty'], $data['qty_unit']);
}
$data['qty_CONV'] = number_format($product_conv->toUnit($unit_to_convert),3,".",",");
$product_ids[] = $product_id;
$qty += $data['qty_CONV'];
$price += $data['price'];
}
}
$p++;
}
if(count($combo)==0 AND $qty >= $qty_search){
$combo = array('product_ids' => $product_ids, 'qty' => $qty, 'price' => $price);
}elseif(($qty >= $qty_search AND $price < $combo['price']) OR
($qty >= $qty_search AND $price == $combo['price'] AND $qty > $combo['qty'])){
$combo = array('product_ids' => $product_ids, 'qty' => $qty, 'price' => $price);
}else{
}
}/// i think it should go here
}
}
}
}
return $combo;
}
Premature end of script headers usually means your script is killed before sending headers to the web server due to a resource limit in RLimitCPU and RLimitMEM directives in the httpd.conf. Either change these directives to allow more CPU and memory to your applications or write more efficient code (3 for loops means processing record^3 times the block inside it. consider rewriting it.)
I am looking to figure out how to use a database of sales completions to influence split testing.
For example, say I have four different page layouts and for each I have the following stats:
Version 1: 6 sales,
Version 2: 1 sale,
Version 3: 3 sales,
Version 4: 4 sales,
Then it would make sense to have version 1 shown most often, and version 4 being next, while version 2 should hardly be shown at all.
Any ideas how I can achieve this?
Very simple solution, mainly depends on how your data looks currently as to what solution is easiest though.
$sales = array
(
1 => 6,
2 => 1,
3 => 3,
4 => 4
);
$weight = array();
foreach ($sales AS $layout => $num_sales)
{
for ($i = 0; $i < $num_sales; $i++)
{
$weight[] = $layout;
}
}
/*
$weight = array
(
1, 1, 1, 1, 1, 1,
2,
3, 3, 3,
4, 4, 4, 4
);
*/
// Pick a random one to use
$layout_to_use = $weight[rand(0, count($weight))];
Let's say you have display the layouts with following weights:
Version 1: 6
Version 4: 4
Version 3: 3
Version 2: 1
Sum of weight is 14 and weight 6 means that you want to show page approximately 6 times in 14 requests.
If you were using database (which I assume you do it would be)
SELECT SUM(weights) FROM version;
Easiest way to implement random selection with different probabilities of hitting item is to sum weights, sort items by their weights and than just iterate trough all items until you hit zero:
$i = rand( 1, $sum);
foreach( $items as $item){
$i -= $item->weight;
if( $i <= 0){
break;
}
}
// $item is now your desired $item
$items should be sorted list of class Item{ public $weight; ... }, because it's most probable that the first element will be used (second the second and so on) and least iterations will be required
What's happening inside:
$i = 12;
// first iteration, $weight = 6
$i = 6; // condition didn't match
// second iteration, $weight = 4
$i = 2; // condition didn't match
// third iteration, $weight = 3
$i = -1; // condition matched
// using version 3