I have a table with five rows for example, and my while loop will display the five rows for me as per normal.
I‘m trying to get the loop to keep looping records until let's say $count = 12. I want to start the counter at 0 and it will end at 12. So, I pretty much want the loop to keep showing the same records randomly until it shows me 12 or so results and then stops.
Simple as while ($a != 12)
$counter = 0;
while ($counter != 12) {
// Do stuff
$counter = rand(0, 24);
}
Related
I've been struggling to make the following piece of code more efficient.
In short;
I've got a database with titles and descriptions. The database will average on 10000 texts. I want to search compare these texts by splitting the text with 'mb_split' and then loop through all other texts to compare if the word exists. Depending on how many comparisons were made, I want to write the article numbers to another table in that database.
The following code works and does the trick, but it takes a really long time to finish and uses a lot of resources. I can't seem to find a way to compare these texts more efficiently.
function compareArticle() {
include '../include/write.php';
$readNewsQuery = "select title,text,articleid,name from texts";
$readNews = $dbwrite->query($readNewsQuery);
if ($readNews) {
//Fetch mysql data as an array
$news = $readNews->fetch_all(MYSQLI_NUM);
// Start foreach to read every article once
foreach ($news as $item) {
echo $item[2].'<br />';
// Start another foreach to loop through the articles to compare with
foreach ($news as $compare) {
$strippedWords = mb_split(' +', $item[0]);
$count = 0;
$compareString = "";
$compareString .= $compare[0];
$compareString .= $compare[1];
$compareString = strtolower($compareString);
// Start yet another foreach to loop through the words
foreach ($strippedWords as $word) {
// I only want to count the words that are longer than 4 characters
if (strlen($word) > 4) {
$woord = strtolower($word);
if (strpos($compareString, $word) && $compare[2] != $item[2]) {
$count++;
}
}
}
if ($count > 5) {
echo $count.'<br />';
//Insert action to write comparison to database (item[2] and compare[2])
}
}
}
}
}
What I'd really like to know; Can I be more efficient? Could I use less loops, or is there an easier way to search the array? If I can be more efficient, could someone give me a nudge in the right direction?
EDIT:
It might be useful to know what data I retrieve and what I want to write to another table:
texts-database is set up to include
| article id | title | text | sourcename
I compare the words in a title with the words of title and text combined for all other articles. If they match enough, I want to write both article id's to another table:
| id | original article id | compared article id |
Once you loop through a news item, you no longer need to compare any other news items to it, for example, if news item 1 didn't match the other 50 news items then when you start checking news item 2 you already know that it doesn't match news item 1.
So instead of looping through the news items twice, you can start your second loop on the current index +1 (you don't need to compare the current news item with itself) of your first news article loop.
Edit: Heres an example loop:
Optimized Loop:
$matches = array();
$a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 10, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 ];
$count = 0;
for ($i = 0; $i < count($a); ++$i) {
for ($j = $i+1; $j < count($a); ++$j) {
if ($a[$i] == $a[$j]) {
array_push($matches, "$i, $j");
}
$count++;
}
}
echo "Optimized n loops: $count\n";
echo 'Matches: ' . count($matches);
// Output
// Optimized n loops: 435
// Matches: 5
Un-optimized Loop
$matches = array();
$count = 0;
for ($i = 0; $i < count($a); ++$i) {
for ($j = 0; $j < count($a); ++$j) {
if ($a[$i] == $a[$j]) {
array_push($matches, "$i, $j");
}
$count++;
}
}
$matches = array_unique($matches); // Dedupe
echo "Un-optimized n loops: $count\n";
echo 'Matches: ' . count($matches);
// Output
// Un-optimized n loops: 900
// Matches: 40
The unoptimized loop includes a lot of duplicate matches (index 1 matches index 5, index 5 matches index 1)
I've executed a lot of tests and made a few changes to my script and now know what the biggest culprit was.
Original case:
Sample size of 10.000;
Execution time: over 600 seconds (ran into max execution time).
Test case:
Completely stripped down version of the original
Sample size of 1000;
Execution time: 24 seconds.
What made the biggest difference?
The biggest difference was changing the location of the following line:
$strippedWords = mb_split(' +', $item[0]);
I moved that line to the first loop instead of the second. This way the title from the first loop only gets split once every 1000 items instead of 1000 times every 1000 items. I measured the differences in time:
mb_split in the second loop:
Total execution time in seconds: 162.17704296112
mb_split in the first loop:
Total execution time in seconds: 24.564566135406
That's an amazingly huge difference. I'm guessing mb_split isn't the easiest thing for PHP to do. Putting mb_split in the wrong part of my code made the script almost 7 times slower :|
strtolower()
After that result, I was curious what differences I could make changing the location of other text modifiers. So, I took strtolower() and put that, where possible, in the first loop as well.
strtolower() in second loop:
Total execution time in seconds: 44.315208911896
strtolower() in first loop:
Total execution time in seconds: 37.129139900208
Although this difference is a lot smaller, it's still a notable difference.
A possible other cause
I am not sure -- as I don't currently have the time to test this -- if this is completely true, but while testing a few cases I found my browser was acting up. When I told PHP to output a lot of information to my browser, the scripts felt like they would run longer and the browser would stop showing information after a while, too.
If the occasion arrises and I have some spare time left, I'll be testing this theory and try to see if my browser can actually screw with the duration of my PHP scripts. I can't seem to find a logical reason as to why it would impact the duration of my PHP script, as I expect the browser to just crash and my PHP script to continue working server sided... but the thought crossed my mind a few times.
anyway, here's the new script
function compareArticle() {
//For timing my script
$time_start = microtime(true);
include '../include/write.php';
$readNewsQuery = "select title,text,articleid,name,datetoday from texts";
$readNews = $dbwrite->query($readNewsQuery);
$dateToday = date("Y-m-d");
if ($readNews) {
//Fetch mysql data as an array
$news = $readNews->fetch_all(MYSQLI_NUM);
}
foreach ($news as $item) {
// Decrease the sample pool
if ($item[4] != $dateToday) {
continue;
}
$strippedWords = strtolower($item[0]);
$strippedWords = mb_split(' +', $strippedWords);
// Start another foreach to loop through the articles to compare with
foreach ($news as $compare) {
$compareString = "";
$compareString .= $compare[0];
$compareString .= $compare[1];
$count = 0;
// Start yet another foreach to loop through the words
foreach ($strippedWords as $word) {
// I only want to count the words that are longer than 4 characters
if (strlen($word) > 4) {
if (strpos(strtolower($compareString), $word)) {
$count++;
}
}
}
for ($x = 0; $x <= 3; $x++) {
for ($y = 0; $y <= 4; $y++) {
if ($y == 0) {
mysql_query("insert into tb_weight_rate_management
(nation,zone_id,rate) values ('Domestic',1,'$del_100')");
}
}
}
hello i am little troubled using for loop....in the code above i have two loops ...1st loop will work 3 times and the the inside loop will work 4 times....
now when i click on submit button then it checks loop one and then enter second loop and inserts data 4 times in the database....which is wrong...i want if $y=0;
then it should insert data only once but it is inserting data 4 times can anyone please correct the above condition
You should use == instead of =. Like this:
if ($y == 0) {
the first loop runs 4 times, hence 4 inserts
In the inner loop you declare $y = 0 on every iteration of the outer loop
for each x iteration, there are one time y=0. and since x executes 4 times (0, 1, 2 and 3) y gets 0 value 4 times as well. if you want to do the insertion only once then you must add x value as well like if($y == 0 and x == 0).
I need help. I need a loop that can execute some codes every 10 rows.
Suppose this is the scenario:
$rows = 15; // The row is for a generated report. I need to put a Thick Border, Horizontally every 10 rows.
This is the loop, and inside it I want another loop or any idea how can I execute some command every 10 rows assuming $row = 15, obviously the command should be executed once since the rows is only 15 and command will execute every 10 rows. Thanks everyone :)
$rows = 15;
for($c=0;$c<$size3;$c++)
{
//Location I want to execute a command every 10 rows.
}
Try for loop for this
for($i = 1;$i <= 40;$i++) {
if($i % 10 == 0) {
// your horizontal code here
} else {
// non horizontal code here
}
}
Edit Remember start the loop from 1 not from 0. See codepad
With 0
With 1
seems there is problem in $rows value, insted of adding condition on $rows %10 ==0 you may try setting one counter $i in loop which will get increment for each row and then you can try adding condition on $i %10 ==0
$startrow = 10 //10 if base 1 or 9 if base 0
$endrow = 15 //you said 15 so lets go with this
for($row = $startrow; $row < $endrow; $row+=10)
{
//do your thing here
}
Since you only want to perform the action once every 10 rows, why not start at row 10, then go by increments of 10 instead of incrementing the row 1 by 1.
This should be more efficient since there will be no wasted loops given your circumstance, it also eliminates the need for checking if the row is divisible by 10.
Sorry for the rather unhelpful title, I am trying to make multiple pages for my foreach statement, as it reaches to a database with 100's of rows. Would I limit the query 1,30 for the first page, then 31-60 the second? If so how would I code that?
$totalRows = 100;// Total rows
$perPage = 30;
$pages = ceil($totalRows/$perPage);
for ($i = 0; $i<=$pages; $i++)
{
$sql = sprintf("SELECT * FROM table LIMIT %s, %s", $i*$perPage, $perPage);
// Execute
}
Queries can carry a significant overhead, so don't do multiple queries. Rather, do a single query, then use PHP to break the results up as you wish. You can use a loop counter along with the % operator to check if it's time to do a break.
For instance, if you are looping through results and your loop variable is $i, then you can do:
if ( $i > 0 && $i % 30 == 0 ) {
// Breaking action here ...
}
To detect every 30th iteration of your loop and implement your logic.
I am using a PHP while loop in order to get data from a database. Ignoring the data that I'm retrieving from the database and concentrating on the amount of records I have fetched, which is 4.
I want to be able to take the 1st record and insert it into a div called "div1" and take the 2nd record and insert it into a div called "div2", take the 3rd record and insert it into a div called "div3".
When it comes to the 4th record I would like to insert it in to the div called "div1" and so on.
I've managed to get every 3rd result, so skipping the 1st and 2nd record and being able to do it with the 3rd using a snippet from the below code:
if ($i % 3 < 2) {
I'm having trouble adapting that to do what I want it to do.
What you want is some variation of
$targetDivNumber = ($i % 3) + 1;
See it in action.
Try something like (pseudo code)
if ($i % 3 = 0) {put in div1}
if ($i % 3 = 1) {put in div2}
if ($i % 3 = 2) {put in div3}
With below code you can do this too:
$cont = 1;
while( fetch results from query )
{
if($cont == 1)
put in div 1;
else if($cont == 2)
put in div 2;
else if($cont == 3)
put in div3;
$cont = $cont <= 3 ? $cont += 1 : 1;
}