Is there a way to make a foreach loop increment by more than one? I am loading a jquery script before each item in a foreach loop and I want the delay to increase by 300 for each item, so that each item animates separately as opposed to at the same time.
So is there another method other than $i++? Like $i++ + 300? Or I am reaching a little too far on this one?
Thanks everyone for responding so quickly. The $i+=300 was exactly what I was looking for. I used this variable to increase the delay time on each of the scripts so it is executed one at a time on each item in the loop. Here is a link to what I used it for. Thanks again!
http://cloudninelabs.com/c9v10/portfolio/
Basically you need to look after the counter yourself.
For example:
$i = 0;
foreach( $somelist as $index => $content ) {
// Do something with $content using $i
$i += 300;
}
Are you looking for something like this:
foreach (array(1, 2, 3, 4) as &$value) {
$value = $value + 300;
}
Your question is kinda unclear to me, but it seems like you can simply use i*300 as your animation interval (e.g. foreach ($foo as $i => $bar) { /*simply use $i*300 as your interval here*/ })
However, just FIY, n a regular for loop you can use $i+=300 (e.g. for ($i=0; $i<10000; $i+=300). It doesn't make much sense to do anything like that in an foreach loop. Instead, keep a separate variable to keep track of that and increase that be 300 every time ($i=0; foreach ($foo as $bar) { ... $i+=300 }).
Related
I am looking for a way to create new arrays in a loop. Not the values, but the array variables. So far, it looks like it's impossible or complicated, or maybe I just haven't found the right way to do it.
For example, I have a dynamic amount of values I need to append to arrays. Let's say it will be 200 000 values. I cannot assign all of these values to one array, for memory reasons on server, just skip this part.
I can assign a maximum amount of 50 000 values per one array. This means, I will need to create 4 arrays to fit all the values in different arrays. But next time, I will not know how many values I need to process.
Is there a way to generate a required amount of arrays based on fixed capacity of each array and an amount of values? Or an array must be declared manually and there is no workaround?
What I am trying to achieve is this:
$required_number_of_arrays = ceil(count($data)/50000);
for ($i = 1;$i <= $required_number_of_arrays;$i++) {
$new_array$i = array();
foreach ($data as $val) {
$new_array$i[] = $val;
}
}
// Created arrays: $new_array1, $new_array2, $new_array3
A possible way to do is to extend ArrayObject. You can build in limitation of how many values may be assigned, this means you need to build a class instead of $new_array$i = array();
However it might be better to look into generators, but Scuzzy beat me to that punchline.
The concept of generators is that with each yield, the previous reference is inaccessible unless you loop over it again. It will be in a way, overwritten unlike in arrays, where you can always traverse over previous indexes using $data[4].
This means you need to process the data directly. Storing the yielded data into a new array will negate its effects.
Fetching huge amounts of data is no issue with generators but one should know the concept of them before using them.
Based on your comments, it sounds like you don't need separate array variables. You can reuse the same one. When it gets to the max size, do your processing and reinitialize it:
$max_array_size = 50000;
$n = 1;
$new_array = [];
foreach ($data as $val) {
$new_array[] = $val;
if ($max_array_size == $n++) {
// process $new_array however you need to, then empty it
$new_array = [];
$n = 1;
}
}
if ($new_array) {
// process the remainder if the last bit is less than max size
}
You could create an array and use extract() to get variables from this array:
$required_number_of_arrays = ceil($data/50000);
$new_arrays = array();
for ($i = 1;$i <= $required_number_of_arrays;$i++) {
$new_arrays["new_array$i"] = $data;
}
extract($new_arrays);
print_r($new_array1);
print_r($new_array2);
//...
I think in your case you have to create an array that holds all your generated arrays insight.
so first declare a variable before the loop.
$global_array = [];
insight the loop you can generate the name and fill that array.
$global_array["new_array$i"] = $val;
After the loop you can work with that array. But i think in the end that won't fix your memory limit problem. If fill 5 array with 200k entries it should be the same as filling one array of 200k the amount of data is the same. So it's possible that you run in both ways over the memory limit. If you can't define the limit it could be a problem.
ini_set('memory_limit', '-1');
So you can only prevent that problem in processing your values directly without saving something in an array. For example if you run a db query and process the values directly and save only the result.
You can try something like this:
foreach ($data as $key => $val) {
$new_array$i[] = $val;
unset($data[$key]);
}
Then your value is stored in a new array and you delete the value of the original data array. After 50k you have to create a new one.
Easier way use array_chunk to split your array into parts.
https://secure.php.net/manual/en/function.array-chunk.php
There's non need for multiple variables. If you want to process your data in chunks, so that you don't fill up memory, reuse the same variable. The previous contents of the variable will be garbage collected when you reassign it.
$chunk_size = 50000;
$number_of_chunks = ceil($data_size/$chunk_size);
for ($i = 0; $i < $data_size; $i += $chunk_size) {
$new_array = array();
foreach ($j = $i * $chunk_size; $j < min($j + chunk_size, $data_size); $j++) {
$new_array[] = get_data_item($j);
}
}
$new_array[$i] serves the same purpose as your proposed $new_array$i.
You could do something like this:
$required_number_of_arrays = ceil(count($data)/50000);
for ($i = 1;$i <= $required_number_of_arrays;$i++) {
$array_name = "new_array_$i";
$$array_name = [];
foreach ($data as $val) {
${$array_name}[] = $val;
}
}
I have a piece of code that iterates over all the related profile records (HAS_MANY) of a team record.
It looks like this:
$team = Team::model()->findByPk(1);
$score = 0;
foreach ($team->profiles as $profile) {
$score += $profile->getScore();
}
Now I need to keep the $team variable, but because of the loop all the profiles will be kept in the profiles property, and use up a ton of memory.
Is there a way to safely clean this up?
I thought about setting profiles to null, but then it obviously remains null (and I don't know if another piece of code needs to access profiles later on)
Like I said, it seems to me you want to keep the $team variable and at the same time you don't, because it uses a lot of memory...
In that case I would unset them one by one:
for ($i=0;for ($i=0, $j = count($team->profiles); $i < $j ; ++$i ){
$score += $team->profiles[$i]->getScore();
unset($team->profiles[$i]);
}
// OR
foreach ($team->profiles as $key => $profile) {
$score += $profile->getScore();
unset($team->profiles[$key]);
}
And just get them from the database again if you need them. Or store them in some kind of temporary file. Don't think there is another way in my opinion.
I have a foreach loop and that is doing some time consuming stuff:
$someHugeArray = [...]; // having beyond 300 to 1000 items
foreach ($someHugeArray as $item) {
$this->applyTimeConsumingMagic($item);
}
When debugging this I try to avoid iterating all of them items, so I am often writing escape code along the lines of:
foreach ($someHugeArray as $i => $item) {
$this->applyTimeConsumingMagic($item);
if ($i > 10) { break; } // #fixme: should not go live
}
And as the comment indicates, something like this did once go live making me feel like an amateur.
Is there some way to break the foreach loop from an XDebug session without writing var_dumpy code? As an IDE I use PhpStorm.
I did not find a way to break a foreach loop on the fly, yet the best next thing one can do is to decrease the array size on the fly.
Set a breakpoint after you set up your array, at best before the loop starts. (It does work inside the loop as well, yet could have weird behavior)
Select Evaluate expression phpstorm's debug window or use shortcut, default should be Alt + Shift + 8
run $someHugeArray = array_slice($someHugeArray, $offset = 0, $length = 10);
Besides array_slice one could also use array_filter if one wants to filter by more specific conditions using a closure.
Now you have a small array, enjoy fast execution time without having to worry to clean up after your debug session.
This will break the loop on the 10th run through - but obviously can be set to say 2 or 3 etc:
$myArray = $this->getHugeDataArray();
$i = 0; //here we set i to 0 so we can count to 10
foreach ($myArray as $key => $value)
{
$i++;
if ($i == 9) {break;}
//rest of actual code
}
I have a php foreach loop and would like to make a condition if true to jump to the index +2.
I know about continue that will go to the next, but my goal is to go to the actual_index + 2.
This is because I have a switch case and I need to do something inside.
I know also that this is possible with the for loop by setting manually the $i, but for the foreach loop, is it possible ?
You cannot do that with foreach(). Use for() instead to control the index yourself
I think you can best use the for loop, this gives you a little bit more control over the loop.
$array = [];
for($i = 0; $i < 100; $i++) {
if ($array[$i]) $i+=2;
}
Why not change your array to a stack? Looping it with a while clause and whenever you wish to skip 1, 2 or many more just pop or shift off from the array ( pop/shift based on the direction of your initial loop ofcourse ).
If I have a foreach construct, like this one:
foreach ($items as $item) {
echo $item . "<br />";
}
I know I can keep track of how many times the construct loops by using a counter variable, like this:
$counter = 0;
$foreach ($items as $item) {
echo $item.' is item #'.$counter. "<br />";
$counter++;
}
But is it possible to do the above without using a "counter" variable?
That is, is it possible to know the iteration count within the foreach loop, without needing a "counter" variable?
Note: I'm totally okay with using counters in my loops, but I'm just curious to see if there is a provision for this built directly into PHP... It's like the awesome foreach construct that simplified certain operations which are clunkier when doing the same thing using a for construct.
No it's not possible unless your $items is an array having contiguous indexes (keys) starting with the 0 key.
If it have contiguous indexes do:
foreach ($items as $k => $v)
{
echo $k, ' = ', $v, '<br />', PHP_EOL;
}
But as others have stated, there is nothing wrong using a counter variable.
There's no easier way - that's kinda what count variables are for.
I'm assuming that you want to know the current count during the loop. If you just need to know it after, use count($items) as others have suggested.
You could tell how many time it WILL loop or SHOULD have looped by doing a
$loops = count($items);
However that will only work if your code does not skip an iteration in any way.
foreach loops N times, where N is just the size of the array. So you can use count($items) to know it.
EDIT
Of course, as noticed by Bulk, your loop should not break (or maybe continue, but I would count a continue as a loop, though shorter...)