I have the following loop that combines two arrays and displays the results in an ordered list:
$list1 = array("make","break","buy");
$list2 = array("home","car","bike");
echo "<ol>";
for($a=0; $a<3; $a++){
for($b=0; $b<3; $b++){
echo "<li".($list1[$a].$list2[$b])."</li>";
}
}
echo "</ol>";
The actual arrays that I have include about 1500 words each, so the list is more than 2 Million combinations long.
Is there a way to display the results with pagination, without generating the entire result set in advance?
For example 500 items per page?
FYI, I don't necessarily need to display the results in an ordered list, if that's going to mess up the pagination.
First, you'll need to be able to start looping from any position in the arrays.
Of course you can use for loops, but I think while loops fit better here.
$length1 = count($list1);
$length2 = count($list2);
//now indexes are initialized to variable values
$a = $var1; //start position $var1 is an integer variable between 0 and ($length1 - 1)
$b = $var2; //start position $var2 is an integer variable between 0 and ($length2 - 1)
while ($a < $length1) {
while ($b < $length2) {
echo '<li>', $list1[$a], ' ', $list2[$b], '</li>';
$b++;
}
$b = 0; //reset inner loop each time it ends
$a++;
}
Next, we need a way to stop both loops if the maximum number of results per page ($limit) is reached before the end of the combinations.
$length1 = count($list1);
$length2 = count($list2);
$a = $var1;
$b = $var2;
$counter = 0;
while ($a < $length1) {
while ($b < $length2) {
echo '<li>', $list1[$a], ' ', $list2[$b], '</li>';
$counter++;
if($counter === $limit) break 2;
$b++;
}
$b = 0;
$a++;
}
Finally, we must find the correct values for $var1 and $var2 above, based on the current $page (starting from page 1) and $limit. This is plain arithmetics that I won't explain here.
Putting it all together:
$length1 = count($list1);
$length2 = count($list2);
$offset = $limit * ($page - 1);
$a = (int)($offset / $length2);
$b = $offset % $length2;
$counter = 0;
while ($a < $length1) {
while ($b < $length2) {
echo '<li>', $list1[$a], ' ', $list2[$b], '</li>';
$counter++;
if($counter === $limit) break 2;
$b++;
}
$b = 0;
$a++;
}
Related
Using while loop to print 10-20 odd numbers on the screen, with <-> (exapmle 11-13-15-17-19, <-> not after 19).How to take the last number so as not to put a -. Thank you.
<?php
$x = 10;
while($x < 20){
$x++;
if($x % 2){
echo $x. "-";
}
}
You can push the odd values to an array and after the loop you can convert the array to a string with the implode (https://www.php.net/manual/en/function.implode.php) function.
$x = 10;
$arr = [];
while($x<20){
$x++;
if ($x%2){
$arr[] = $x;
}
}
echo implode(",", $arr);
// output will be a comma seperated string
without (helper)array
You can use rtrim() (https://www.php.net/manual/de/function.rtrim.php) funktion.
$str = "1,2,3,";
echo rtrim($str,",");
As mentioned in the comments, have a boolean variable say firstTime. If this is true, don't prepend a hyphen, else if it is false, prepend it with a hyphen.
<?php
$x = 10;
$firstTime = true;
while($x < 20){
$x++;
if($x % 2){
echo ($firstTime ? "" : "-") . $x;
$firstTime = false;
}
}
Turn the limit number into a variable and use a ternary operator to print out a dash only if $x + 1 < $limit
https://paiza.io/projects/EDj6-u-FAcYxYoR7ON_cvg
<?php
$x = 10;
$y = 20;
while($x < $y){
$x++;
if($x % 2){
echo ($x + 1 === $y) ? $x : $x. "-";
}
}
?>
Simple approach
Imagine you are printing a list of numbers from 10 to 20. If it's an even number, print the "-" symbol and if it's odd number, print the number.
<?php
$start = 10;
$end = 20;
while($start<$end)
{
$n=$start;
if($n>10)
echo ($n%2==0)?"-":$n; //the gist is here
$start++;
}
I need to divide an integer value into x parts (dynamic) using php inside a for loop (Note:Both the number to be split and the split value are dynamic)
for eg: I have a value 127 and divide it into 2parts it would be 63 and 64.
$number = y; //for example is 127
$parts = x; //for example is 2
for($i=1;$i<$parts;$i++){
//first iteration should output 63
//second iteration should output 64 (the last iteration should be always higher is the $number is not divisible by $parts)
}
Check out this example. I use the modulo operator. This works whether it's an even or odd number. You could wrap this all in a function also.
$x = 127;
$a = 0;
$b = 0;
$a = floor($x/2);
$b = ($x % 2) + $a;
echo "A: " . $a . "| B: " . $b; //A: 63| B: 64
Try it in a function.
function remainders($x, $num) {
$results = array();
$firstOp = floor($x / $num);
for($a = 1; $a <= $num; $a++) {
if($a != $num) {
$results[] = $firstOp;
}
else {
if($x % 2 == 1) {
$results[] = $firstOp + 1;
}
else {
$results[] = $firstOp;
}
}
}
return $results;
}
Then you can iterate through the returned array or do what you want.
$splitNum = remainders(183, 4); //split the number 183 in 4 parts.
foreach($splitNum as $var) { echo $var . ", "; }
Try this:
$number = 127; //for example is 127
$parts = 3; //for example is 3
$sep = ", ";
$n=floor($number/$parts);
for($i=1;$i<=$parts;$i++){
if ($i==$parts) {
$n=$number-($n*($i-1));
$sep="";
}
echo $n.$sep;
}
I use the following to find out the common divisors.
But in some case the count of divisors are not satisfied.
My Code :
$x = 66928;
$y = 66992;
$c_a = [];
$c_b = [];
$d = 1;
while ($d_a <= $x) {
if (is_int($x / $d)) $c_a[] = $d;
$d++;
}
$d = 1;
while ($d_b <= $y) {
if (is_int($y / $d)) $c_b[] = $d;
$d++;
}
echo count($c_a);
echo count($c_b);
// Output
$c_a = 20;
$c_b = 20;
Because, in some cases, it won't work.
Is this type of calculation is right ?
or any suggestions ?
As per asked in comment, to count the common factors of the two no. will be as like this.
<?php
$a = 66928;
$b = 66992;
$min = ($a < $b ) ? $a : $b;
$commomn_factors_count = 0;
for ($i = 1; $i < $min/2; $i++) {
if (($a%$i==0) && ($b%$i==0)) {
$commomn_factors_count++;
}
}
var_dump($commomn_factors_count);
You can you this code to get the fastest result to find the number of common divisors between two numbers:
// Function to calculate gcd of two numbers
function gcd($a, $b)
{
if ($a == 0)
return $b;
return gcd($b % $a, $a);
}
/* Function to calculate all common
* divisors of two given numbers
* a, b --> input integer numbers
*/
function commDiv($a, $b)
{
// find gcd of a, b
$n = gcd($a, $b);
// Count divisors of n.
$result = 0;
for ($i = 1; $i <= sqrt($n);
$i++)
{
// if 'i' is factor of n
if ($n % $i == 0)
{
// check if divisors
// are equal
if ($n / $i == $i)
$result += 1;
else
$result += 2;
}
}
return $result;
}
// Driver Code
$a = 10; $b = 15;
echo(commDiv($a, $b));
I want to tell my array to start from key position 2 and then loop through the entire array, including the values before key position 2. I just want to use one array and specify the key position I start looping from. For example, here I am using array_splice, but it does not do what I want it to, could you help me please?
$names = array('Bill', 'Ben', 'Bert', 'Ernie');
foreach(array_slice($names, 2) as $name){
echo $name;
}
foreach(array_slice($names, 3) as $name){
echo $name;
}
If the keys are irrelevant, you can splice the array twice, and merge the resulting arrays, like this:
$names = array('Bill', 'Ben', 'Bert', 'Ernie');
$start = 2;
foreach( array_merge( array_slice($names, $start), array_slice( $names, 0, $start)) as $name){
echo $name;
}
You can see from the demo that this prints:
BertErnieBillBen
Alternatively, for efficiency, you can use two loops that are aware of wrapping around to the beginning, which will be more efficient since you are operating on the original array and not creating copies of it.
$start = 2;
for( $i = $start, $count = count( $names); $i < $count; $i++) {
echo $names[$i];
}
$i = 0;
while( $i < $start) {
echo $names[$i++];
}
You could also turn this into one single loop, and just encapsulate the logic for wrapping around inside the for.
$limit = 2; //so you can set your start index to an arbitrary number
$fn= function($a,$b) use ($limit){
if(($a < $limit && $b < $limit)
|| ($a >= $limit && $b >=$limit)) //$a and $b on the same side of $limit
return $a < $b ? -1 : ($a==$b ? 0 : 1);
if($a < $limit && $b > $limit) return 1; //because $a will always be considered greater
if($a >= $limit && $b < $limit) return -1; //because $b will always be considered greater
};
uksort($arr, $fn);
foreach($arr as $v) echo $v;
The code below will create an array for all possible combination that can occur when you have four different variables. The variables always need to equal 1. The for loops I have created work and I understand how to make this work for more variables, but can I make this dynamic? I need to have a function that has how many variables there are as a parameter. If there are three variables create the three forloops. If there are 10... create the 10 corresponding for loops to determine all possible combinations.
$anarray2 = array();
for( $a = 1; $a <= 97; $a++ ) {
for( $b = 1; $a + $b <=98 ; $b++ ) {
for( $c = 1; $a + $b + $c <= 99; $c++ ) {
$d = 100 - ( $a + $b + $c );
$var_1 = $a / 100;
$var_2 = $b / 100;
$var_3 = $c / 100;
$var_4 = $d / 100;
$anarray2[] = array( $var_1, $var_2, $var_3, $var_4 );
}
}
}
print_array( $anarray2 );
You're effectively looking to share out I identical items to N people in all of the different possible ways.
If there is one person (N==1), then there is only one way to do this - give that person all I items.
If there is more than one person (N>1), then we can consider how many items can be assigned to the first person, and then what the possible assignments are for the remaining N-1 people in each case.
This leads to a nice recursive solution. Firstly we solve the problem for N=1:
function assign($I, $N) {
$anarray = array();
if ($N == 1) {
$anarray[] = array($I);
} else {
// Coming up...
}
return $anarray;
}
Now we solve the problem for N=k (some constant) in terms of N=k-1 - that is, we solve the problem using the solution to a smaller problem. This will reach all the way back to the solution when N=1.
function assign($I, $N) {
$anarray = array();
if ($N == 1) {
$anarray[] = array($I);
} else {
for ($i = $I; $i < $I; $i++) {
foreach (assign($I - $i, $N - 1) as $subproblem) {
$anarray[] = array_merge(array($i), $subproblem);
}
}
}
return $anarray;
}
Something like that should do the job.