Modulus inside loop - php

I have an array that I am looping through and breaking up into chunks of 50. However occasionally the number of items inside that array are more than what fits inside that chunk of 50 ex.:
$array = array(); // has 220 rows
for ($i = 0; $i < count($array); $i++) {
$j[] = $i;
if ($i % 50 == 1) {
print_r($j); // do something here with the 50 rows
$j = null;
}
}
The problem here is that this will not print anything after 201. I know there is some algebraic math involved in solving this but I am drawing a blank. Its times like these where I really wish I had paid attention in math class back in high school.

I think array_chunk fits up your requirement and no maths required.
$result_array = array_chunk($array, 50, true);

Add additional condition
if ($i % 50 == 1 || count($array)-1 == $i)

You just have to redeclare the array is my guess:
$array = array(); // has 220 rows
for ($i = 0; $i < count($array); $i++) {
$j[] = $i;
if ($i % 50 == 1) {
print_r($j); // do something here with the 50 rows
$j = array() ;
}
}
Once you perform $j = null there is no way you can do $j[] = $i

$array = array(); // has 220 rows
for ($i = 0; $i < count($array); $i++) {
$j[] = $i;
if ($i % 50 == 1) {
doSomething($j); // do something here with the 50 rows
$j = array(); // reset the array
}
}
doSomething($j); // with the last 20 entries
After your loop is finished, you will have the remaining 201 through 220 entries in $j, so just do your stuff again.

array_chunk
might be useful. Basically splits the array into chunks returning a multi dimensional array

Related

Optimisation of O(n4) complexity to O(n) in PHP nested for loop

I am writing one logic to iterate numbers first and then additional logic to putting them into particular subset of array.
What does this code do :
Code accept first $n
its create array of $n number from 1 to $n
Then started converting to subset of $main_array to possible one like
['1'] [1,2] [1,2,3] [2] [2,3] [3] etc. same like this
After creating subset i am counting those some subset which satisfy condition
Condition is xyz[0] should not come in subset with abc[0] vice versa xyz[i] should not come in subset abc[i]. Example 2 and 3 is coming subset then dont count that subset, same 1 and 4 is coming then dont count
here is my nested for loop :
$n = 1299;
$main_array = range(1,$n);
$counter = 0;
$count = sizeof($abc); // $abc and $xyz size will same always.
$abc = [2,1];
$xyz = [3,4];
for ($i=0; $i <$n; $i++) {
for($j = $i;$j < $n; $j++){
$interval_array = array();
for ($k = $i; $k <= $j; $k++){
array_push($interval_array,$main_array[$k]);
}
$counter++;
for ($l=0; $l < $count ; $l++) {
//if block here to additional condition using in_array() php function. which do $counter--
if(in_array($abc[$l], $interval_array) &&
in_array($xyz[$l], $interval_array)){
$counter--;
break;
}
}
}
}
$main_array i have to create on the spot after receiving $n values.
Following is cases :
when running $n = 4 its run in 4s
when running $n = 1200 or 1299 or more than 1000 its run in 60s-123s
Expected execution timing is 9s. I reduce from 124s to 65s by removing function calling inside for loop but its not coming to point.
Expectation of code is if i have array like
$array = [1,2,3];
then
subset need to generate :
[1],[1,2],[1,2,3],[2],[2,3],[3]
Any help in this ?
It's difficult to test performance against your experience, but this solution removes one of the loops.
The way you repeatedly build $interval_array is not needed, what this code does is to just add the new value from the main array on each $j loop. This array is then reset only in the outer loop and so it just keeps the last values and adds 1 extra value each time...
for ($i=0; $i <$n; $i++) {
$interval_array = array();
for($j = $i;$j < $n; $j++){
array_push($interval_array,$main_array[$j]);
// Check output
echo implode(",", $interval_array)."\n";
$counter++;
for ($l=0; $l < $count ; $l++) {
if(in_array($abc[$l], $interval_array) &&
in_array($xyz[$l], $interval_array)){
$counter--;
break 2;
}
}
}
}
adding "\n" to better understanding for subset flow.
import datetime
N = list(range(1, int(input("N:")) + 1))
affected_list = list(map(int, input("affected_list").split()))
poisoned_list = list(map(int, input("poisoned_list").split()))
start_time = datetime.datetime.now()
exclude_list = list(map(list, list(zip(affected_list, poisoned_list))))
final_list = []
for i in range(0, len(N)):
for j in range(i + 1, len(N) + 1):
if N[i:j] not in exclude_list:
final_list.append(N[i:j])
print(final_list)
end_time = datetime.datetime.now()
print("Total Time: ", (end_time - start_time).seconds)

Can someone help me return a value?

I have created a loop which returns a random number between two values. Cool.
But now I want the script to return the following value too: The number of unique numbers between two similar numbers.
Example:
4
5
8
22
45
3
85
44
4
55
15
23
As you see there is a double which is the four and there are 7 numbers inbetween. So I would like the script to echo these numbers two so in this case it should echo 7 but if there are more doubles in the list it should echo all the numbers between certain doubles.
This is what I have:
for ($x = 0; $x <= 100; $x++) {
$min=0;
$max=50;
echo rand($min,$max);
echo "<br>";
}
Can someone help me or guide me? I'm learning :)
Thanks!
So You need to seperate script for three parts:
getting randoms and save them to array (name it 'result'),
analyze them,
print (echo) results
Simply - instead of printing every step of loop, save them to array(), exit loop, analyze every item with other, example:
take i element of list
check is i+j element is the same
if is it the same - save j-i to second array() (name it 'ranges')
And after this, print two arrays (named by me as 'result' and 'ranges')
UPDATE:
Here's solution, hope You enjoy:
$result = array(); #variable is set as array object
$ranges = array(); #same
# 1st part - collecting random numbers
for ($x = 0; $x < 20; $x++)
{
$min=0;
$max=50;
$result[] = rand($min,$max); #here's putting random number to array
}
$result_size = count($result); #variable which is containg size of $result array
# 2nd part - getting ranges between values
for ($i = 0; $i < $result_size; $i++)
{
for ($j = 0; $j < $result_size; $j++)
{
if($i == $j) continue; # we don't want to compare numbers with itself,so miss it and continue
else if($result[$i] == $result[$j])
{
$range = $i - $j; # get range beetwen numbers
if($range > 0 ) # this is for miss double results like 14 and -14 for same comparing
{
$ranges[$result[$i]] = $range;
}
}
}
}
#3rd part - priting results
echo("RANDOM NUMBERS:<br>");
foreach($result as $number)
{
echo ("$number ");
}
echo("<br><br>RANGES BETWEEN SAME VALUES:<br>");
foreach($ranges as $number => $range)
{
echo ("For numbers: $number range is: $range<br>");
}
Here's sample of echo ($x is set as 20):
RANDOM NUMBERS:
6 40 6 29 43 32 17 44 48 21 40 2 33 47 42 3 22 26 39 46
RANGES BETWEEN SAME VALUES:
For numbers: 6 range is: 2
For numbers: 40 range is: 9
Here is your fish:
Put the rand into an array $list = array(); and $list[] = rand($min,$max); then process the array with two for loops.
$min=0;
$max=50;
$list = array();
for ($x = 0; $x <= 100; ++$x) {
$list[] = rand($min,$max);
}
print "<pre>";print_r($list);print "</pre>";
$ranges = array();
$count = count($list);
for ($i = 0; $i < $count; ++$i) {
$a = $list[$i];
for ($j = $i+1; $j < $count; ++$j) {
$b = $list[$j];
if($a == $b) {
$ranges[] = $j-$i;
}
}
}
print "<pre>";print_r($ranges);print "</pre>";

Print all combination of sub range within a given array

I want to print all combination of sub range in an given array. I have an array of y number of elements in it from which I want to print all combination of contiguous sub range.
Constraint is : each sub range should have at least 2 elements and each element in sub range should be contiguous. It should share same border of each element.
For example, We have an array of 7 elements [11,12,13,14,11,12,13]
So, the total number of sub range combination will [7 * (7-1) /2] = 21
So, the Output will be something like this:
11,12
12,13
13,14
14,11
11,12
12,13
11,12,13
12,13,14
13,14,11
...
11,12,13,14 and so on (total 21 combination as per above array)
we should not print any combination which is not contiguous. example: [11,12,14] is not valid combination as it skips the element "13" in between.
I am able to print the combination with 2 elements but i am having difficulty in printing more then 2 elements combination.
Below is what I have tried so far.
$data=array("11","12","13","14","11","12","13");
$totalCount=count($data);
for($i=0;$i<$totalCount;$i++){
if(($i+1) < ($totalCount)){
echo "[".$data[$i].",".$data[$i+1]."]<br>";
}
}
You can do that:
$arr = [11,12,13,14,11,12,13];
function genComb($arr, $from = 1, $to = -1) {
$arraySize = count($arr);
if ($to == -1) $to = $arraySize;
$sizeLimit = $to + 1;
for ($i = $from; $i < $sizeLimit; $i++) { // size loop
$indexLimit = $arraySize - $i + 1;
for ($j = 0; $j < $indexLimit; $j++) { // position loop
yield array_slice($arr, $j, $i);
}
}
}
$count = 0;
foreach (genComb($arr, 2) as $item) {
echo implode(',', $item), PHP_EOL;
$count++;
}
echo "total: $count\n";
Casimir et Hippolyte was faster, but you can gain huge performance by processing each contiguous section independently:
function getCombos(&$data) {
$combos = array();
$count = count($data);
$i = 0;
while ($i < $count) {
$start = $i++;
while ($i < $count && $data[$i - 1] + 1 == $data[$i]) // look for contiguous items
$i++;
if ($i - $start > 1) // only add if there are at least 2
addCombos($data, $start, $i, $combos); // see other answer
}
return $combos;
}

Evenly reducing an indexed array by 10%

I have an array filled with data over the period of a month. The data is computed for every 15 minutes over that period, meaning it's got about 2880 entries.
I need to reduce it by about 10% in order to display the data in a chart (288 data points will render much more nicely than 2880).
Here's what I've tried (it works, but it might be a very bad method):
$count = count($this->Data1Month);
for($i = 0; $i < $count; $i += 10) {
$tempArray[] = $this->DataMonth[$i];
}
$this->Data1Month = $tempArray;
I think you have the most efficient solution, but you do have a mistake though. Array indexes start at zero so 0+10 needs to be 9, like so:
$count = count($this->Data1Month);
for($i = 0; $i < $count; $i += 9) {
$tempArray[] = $this->DataMonth[$i];
}
$this->Data1Month = $tempArray;

Continue in while with mysql_fetch_assoc

I have a few lines of code, but can't find the right way to use it properly.
$cc = 0;
$tt = 50;
while ($row = mysql_fetch_assoc($result)) {
//building array with values from DB.
if (++$cc < $tt)
continue;
for ($i = 0; $i < $tt; $i++) {
//Work with the array
}
}
Let's say I have 133 results in DB. It'll get first 50 - do something in the for loop, then 50 more, will go thru the for loop again and will stop.
The last 33 results will be untouched.
It'll get them, but cause can't reach 50 will stop and they won't go through the for loop.
My problems is how to "send" them in the loop down there?
Move the for loop in a function and call it after the while loop:
$cc = 0;
$tt = 50;
while ($row = mysql_fetch_assoc($result)) {
//building array with values from DB.
if (++$cc < $tt) continue;
work_with_array($array);
}
if($cc) work_with_array($array);
function work_with_array($array) {
for ($i = 0; $i < count($array); $i++) {
//Work with the array
}
}
Try this:
$i = 0
while ($row = mysql_fetch_assoc($result)):
if($i < 50):
//Code when $i is less than 50
//Insert code here
elseif($i > 50 && $i < 100):
//Code when $i is more than 50 but less than 100
//Insert code here
elseif($i > 100):
//Code when $i is more than 100
//Insert code here
endif;
$i++;
endwhile;
So all results are going through this loop. If $i is less than 50 (or if the result is less than 50) then some code is executed, or if $i is more than 50 but less than 100 then some different code is executed. Finally if $i is more than 100 then some other code is executed.
Do you understand?
You could try:
$i = 0
while ($row = mysql_fetch_assoc($result) && $i < 100):
if($i < 50):
//Code when $i is less than 50
else:
//Code more than or equal to 50
endif;
$i++;
endwhile;
All the continues inside the loop seem unneccesary. If you're simply trying to process the entire result set and do something in chunks, you can do this
$cc = 0;
$tt = 50;
$result_array = array();
// this will chunk your array into blocks
while ($row = mysql_fetch_assoc($result)) {
//building array with values from DB.
$result_array[intval($cc++/$tt)] = $row;
}
// at this point you should have result_array with indexes:0,1,2 and have subarrays with 50, 50, 33 entries each.
foreach ($result_array as $k=>$sub_array) {
//Work with your sub array
foreach ($sub_array as $one_row)
{
// do something with the row
}
}
I do agree with #Col.Shrapnel though. Why are you creating another array inside the while loop just to go through that array one row at a time to do something? It would've made sense if you send out a batch of data at once (like bulk insert into db, sure) but to loop through again seems odd. Why can't you do the same right in the while loop

Categories