php continuously loop through array [duplicate] - php

This question already has answers here:
PHP - Sequence through array and repeat [modulo-operator]
(3 answers)
Closed 9 days ago.
I'm wondering if there is a function built into PHP that I could leverage to loop through an array, and reset to the beginning to continue to loop again.
The use of this would be an array of colors for an SVG that is created with a PHP function. I think my max case would be X but I want to make sure if I have more than X I restart with the color codes.
Below is the code I have that works, but wondering if there is a built in function to do this.
$color_array = array( 1 => '#00cc00', 2=> '#B45F04', 3=> '#0101DF', 4=> '#B40486', 5=> 'F1F105', 6=>'F10505');
$num_color_array = count($color_array); //get number of elements
foreach(loop through array 1){ //psuedo code
$array_color_index = 1;
foreach(loop throguh array 2){ //psuedo code
if($array_color_index > $num_color_array){
$array_color_index = 1; //if > num elements reset
}
$color_fill = $color_array[$array_color_index]; //pull the color code
fill:'.$color_fill.' //use the color code here...simplified for example...
$array_color_index++; //increment index
}
}

You could use something like this (using the modulus):
$color_array = array('#f00', '#0f0', '#00f');
$elements = get_some_colorable_elements();
// For each element in $elements, the modulus returns a value between 0 and the size of $color_array
for ($i = 0; $i < count($elements); $i += 1) {
$colorForElement = $color_array[$i % count($color_array)];
fill_color_for_element($colorForElement);
}
As far as I know there is no built in function specifically for this purpose (other than the modulus).

Try using the modulus:
$color_fill = $color_array[$array_color_index % $num_color_array];
You're getting the remainder of your index divided by the total number of elements.. so when the index = number of elements, remainder = 0, and then it cycles.

If you loop through an array and then start at the beginning again using anything like a foreach() you're essentially creating an infinite loop. I don't think there's a basic function for it, but it's fairly easy to make one. Of course, you'd have to use BREAK to end it.
A function like this would do (it's a Generator, so you need an up to date PHP version)
function constantLoop( $array ) {
while(true) {
foreach( $array as $element ) {
yield $element;
}
}
}
You can use it like this:
foreach( constantLoop( $array ) as $value );
But you HAVE to break, because as the name says, it'll keep looping forever.

Related

empty array whenever it reaches a threshold

I've a loop that generates an array of all possible combinations of binary bits by giving the number of bits, but I got a memory issue when the number of its exceeds 20.
So I'm looking for a way to remove or empty the previous array values for example if the array reaches 1k or 2k values, here's the code :
for ($i = 1; $i <= ($listN - 1); $i++) {
$reverseBits = array_reverse($bits);
$prefixBit = preg_filter('/^/', '0', $bits);
$prefixReverseBits = preg_filter('/^/', '1', $reverseBits);
$bits = array_merge($prefixBit, $prefixReverseBits);
unset($prefixBit, $prefixReverseBits, $reverseBits);
}
I've tried this one but it does not work, the array will be fully empty outside the loop :
if(count($bits) > 1000){
unset($bits);
$bits = array();
}
Thank you for your help
Your code simply does nothing, if the $bits array is empty, because array_reverse and preg_filter do not modify the array size and array_merge only adds the existing numers together. So en empty array will always stay empty.
Instead set your "emtpy" array to the 1 bit default array ['0','1']:
if(count($bits) > 1000){
$bits = array('0','1');
}
In case you want to keep your "last 1000" results instead of deleting all reasults you got so far think about using $bits = array_slice($bits, 0, 1000); at the beginning of your loop.
For achieving something like that, you simply have to do something of the sort:
if(count($bits) > 1000){
$bits = array_slice($bits, 1000);
}
This will slice the array from the offset 1000 and leave the rest of the items of the array, intact.
Reference: http://php.net/manual/en/function.array-slice.php

count the elements in array except of specific element

For example i have an array like this [-1,-1,-1,-1,-1,-1,2.5,-1,-1,8.3]
I want to count the element which are not -1 like except of the -1. Is there any function in php to get this ? One approach which i think is
Count the total array - count of the -1 in the array.
how can we achieve this.
P.S : please provide me a comment why this question deserve negative vote.
Like #MarkBaker said, PHP doesn't have a convenient function for every single problem, however, you could make one yourself like this:
$arr = [-1,-1,-1,-1,-1,-1,2.5,-1,-1,8.3];
function countExcludingValuesOfNegativeOne ($arr) {
return count($arr) - array_count_values(array_map('strval', $arr))['-1'];
}
echo countExcludingValuesOfNegativeOne($arr); // Outputs `2`.
It just counts the whole array, then subtracts the number of negative 1s in the array. Because PHP throws an error if any element in the array isn't a string 1 when using array_count_values, I've just converted all elements of the array to a string using array_map('strval', $arr) 2
you can use a for loop counter skipping for a specific number.
function skip_counter($array,$skip){
$counter = 0;
foreach ($array as $value) {
if ($value != $skip) $counter++;
}
return $counter;
}
then you call skip_counter($your_list, $number_to_be_skipped);

php maximum values to show in a list in random order? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Output array elements randomly with PHP
Lets say we have this code:
<? if (isset($specialoffers)) { ?>
<? foreach ($specialoffers as $value) { ?>
<div>product #</div>
<?};?>
<?};?>
For example this list may be different everytime, it may have 1 product, and it may have 58 products. I want do display only 10 products in the list and in a random order.
How to do that?
I would like not to touch the SQL query!
Take a look at the array_rand function which takes one or more random elements from an array.
So, you could do something along the lines of:
foreach (array_rand($specialoffers,10) as $key)
do_something_interesting_with $specialoffers[$key];
$specialoffers = array_splice( shuffle($specialoffers), 0, 9 );
Something like this might work.
You can use shuffle() to randomize the array.
http://php.net/manual/en/function.shuffle.php
You can do that with Reservoir Sampling which is even needed if the number of elements would exhaust your memory (and are presented through an iterator):
$randoms = new RandomIterator($specialoffers, 10);
foreach ($randoms as $value) {
...
}
You can find the source-code of the RandomIterator class as Gist.
Please try example for getting random value from assoc arrays;
function array_random_assoc( $arr, $num = 1) {
$keys = array_keys($arr);
shuffle($keys);
$r = array();
for ($i = 0; $i < $num; $i++) {
$r[$keys[$i]] = $arr[$keys[$i]];
}
return $r;
}
$specialoffers = (array_random_assoc($data_array, 10));

PHP Undefined offset error repeated

I'm trying to run a PHP script that finds all the numbers divisible by 3 or 5, dumps them into an array, and adds all the values together. However, When I try to run it, I get a number output (I don't know if it's correct or not) and several hundred errors. They start out with:
Notice: Undefined offset: 1 in G:\Computer Stuff\WampServer\wamp\www\findthreesandfives.php on line 18
Then the offset number increases by increments of 1-3 (randomly, I haven't seen a pattern yet). I can't figure out what's wrong. Here's my code:
<?php
function loop($x)
{
$a = array(); //array of values divisible by 3 or 5
$l = 0; //length of the array
$e = 0; //sum of all the values in the array
for ($i=0; $i<=$x; $i++){ //this for loop creates the array
$n3=$i%3;
$n5=$i%5;
if($n3 === 0 || $n5 === 0){
$a[$i]=$i;
$l++;
}
}
for ($v=0; $v<=$l; $v++){ //this loop adds each value of the array to the total value
$e=$e + $a[$v];
}
return $e;
}
echo loop(1000);
?>
Someone please help...
The problem in your code is the following line:
$a[$i]=$i;
Should be:
$a[count($a)] = $i;
This is because the value of $i is always increasing, so using $i as your pointer will create gaps in the array's indices. count($a) returns the total number of items in the given array, which also happens to be the next index.
EDIT: #pebbl suggested using $a[] = $i; as a simpler alternative providing the same functionality.
EDIT 2: Solving the subsequent problem the OP described in the comments:
The problem seems to be that $l is greater than the number of items in $a. Thus, using count($a) in the for loop should fix your subsequent error.
Try replacing:
for ($v=0; $v<=$l; $v++){
With:
for ($v=0; $v<=count($a); $v++){
I found the same problem as #zsnow said. There are gaps within $a. The if condition allowed the gaps making the assignment skip some indexes. You can also use this
foreach ($a as $v){ //this loop adds each value of the array to the total value
$e=$e + $a[$v];
}
should actually be
foreach ($a as $v){ //this loop adds each value of the array to the total value
$e=$e + $v;
}

Which is the best way to remove middle element of associative array in PHP?

Please tell me which is the best way to unset middle element of associative array in PHP?
Suppose I have an array of 10,000 elements and I want to remove middle element of that array, which is efficient way to remove middle element?
$temp = array('name1'=>'value1','name2'=>'value2',...,'name10000'=>'value10000');
$middleElem = ceil(count($temp) / 2);
$i = 0;
foreach ($temp as $key=>$val) {
if ($i == $middleElem) {
unset($temp[$key]);
break;
}
$i++;
}
Is above code efficient way?
Considering $array is your array, this code remove the middle element if it has odd number of elements. If its event it'll remove the first of 2 middle elements.
$i = round(count($array)/2) - 1;
$keys = array_keys($array);
unset ($array[$keys[$i]]);
Test Result: http://ideone.com/wFEM2
The thing you have to figure out is what you want to do when you have an array with an even number of elements. What element do you want to get then?
The above code picks the 'lower' element, the code could easily be edited to make it pick the 'higher' element. The only thing you have to check is (what all others answers failed to do) what happens if you have three elements. It doesn;t pick the middle element, but the last. So you would have to add a check for that then.
$temp = Array("name1"=>"value1","name2"=>"value2",...,"name10000"=>"value10000");
$middleElem = ceil(count($temp)/2);
$keys = array_keys($temp);
$middleKey = $keys[$middleElem];
unset($temp[$middleKey]);
There ^_^
I think it's a proper way to do it. Try this:
array_remove_at( $temp, ceil(count($temp) / 2) - 1);
function array_remove_at(&$array, $index){
if (array_key_exists($index, $array)) {
array_splice($array, $index, 1);
}
}
You can find the size of the array, divide that number by two and then proceed to remove the element. Not sure about the performance isssues about that though
Firstly, I wouldn't worry too much about what is the most efficient way at this point. You're much better off coding for how easy the code is to read, debug and change. Micro-optimisations like this rarely produce great results (as they're often not the biggest bottlenecks).
Having said that, if you want a solution that is easy to read, then how about using array_splice.
$temp = array('name1'=>'value1','name2'=>'value2',...,'name10000'=>'value10000');
$middleElem = ceil(count($temp) / 2);
array_splice( $temp, $middleElem, 1 );
I would take it that the following code is more efficient, because you don't have to execute it in a loop. I generally follow the same pattern as Kolink, but my version checks if there actually is a "middle element". Works on all types of arrays, I think.
<?php
for( $i = 0; $i <= 9; $i ++ ) {
$temp['name'.$i] = 'value'.$i;
}
if( ( $count = count( $temp ) ) % 2 === 0 ) {
/** Only on uneven arrays. */
array_splice( $temp, ( ceil( $count ) / 2 ), 1 );
}
var_dump( $temp );
EDIT: Thavarith seems to be right; array_splice is much faster than simply unsetting the value. Plus, you get the added benefit of not having to use array_keys, as you already now at what $offset the middle is.
Proper way seems to be:
unset(arr[id]);
arr = array_values(arr);
For first removing element at index id and then re-indexing the array arr properly.
unset($myArray[key])
since your array is associative, you can drop any element easily this way

Categories