This question already has answers here:
Removing a value from a PHP Array
(3 answers)
Closed 8 years ago.
I have an array that looks like this
$hours_worked = array('23',0,'24',0)
What want to do is to loop through the array and remove the element that contains 0
What I have so far is:
for($i = 0; $i < count($hours_worked); $i++)
{
if($hours_worked[$i] === 0 )
{
unset($hours_worked[$i]);
}
}
However the result I get is $hours_worked = array(23,24,0). I.e. it does not remove the final element from the array. Any ideas?
The problem with this code is that you are calculating count($hours_worked) on each iteration; once you remove an item the count will decrease, which means that for each item removed the loop will terminate before seeing one item at the end of the array. So an immediate way to fix it would be to pull the count out of the loop:
$count = count($hours_worked);
for($i = 0; $i < $count; $i++) {
// ...
}
That said, the code can be further improved. For one you should always use foreach instead of for -- this makes the code work on all arrays instead of just numerically indexed ones, and is also immune to counting problems:
foreach ($hours_worked as $key => $value) {
if ($value === 0) unset($hours_worked[$key]);
}
You might also want to use array_diff for this kind of work because it's an easy one-liner:
$hours_worked = array('23',0,'24',0);
$hours_worked = array_diff($hours_worked, array(0)); // removes the zeroes
If you choose to do this, be aware of how array_diff compares items:
Two elements are considered equal if and only if (string) $elem1 ===
(string) $elem2. In words: when the string representation is the
same.
Try foreach loops instead
$new_array = array();
foreach($hours_worked as $hour) {
if($hour != '0') {
$new_array[] = $hour;
}
}
// $new_array should contain array(23, 24)
Related
This question already has answers here:
How to filter an array by a condition
(9 answers)
Closed 5 years ago.
Output must be "This is a testing string sample". it is correct for small array filter with index value if filter array value are more than 100 values we can't assign static index number.How can be loop to filter to my base array. i know can use array_diff but i just learn how work with for loop.
<?php
$arr = array("This","is","testing","a","string",";","sample");
$filter = array(";","a");
for($i=0; $i < count($arr); $i++){
if($arr[$i] == $filter[0] || $arr[$i] == $filter[1]){
continue;
}
echo "$arr[$i] ";
}
?>
You could filter multiple values from an array using array_diff. For this case, you don't need an loop.
$filtered = array_diff($arr, $filter);
In general, there's an function, called array_filter to filter values from an array given a predicate.
$filtered = array_filter($arr, function ($item) use ($filter) {
return !in_array($item, $filter);
});
To print your result, you could just use join to combine the whole array with a "glue".
echo join(' ', $filtered);
To fix your example, you could also loop over your filter and use continue 2, to continue the outer loop. But this is very bad practice and leads to unreadable code. So don't do this! A better solution would be an "found" flag and another check after the inner loop, if the flag is set...
for($i=0; $i < count($arr); $i++){
for ($j = 0; $j < count($filter); $j++) {
if ($arr[$i] == $filter[$j]) {
continue 2;
}
}
echo "$arr[$i] ";
}
Use in_array
foreach ($arr as $item) {
if (in_array($item, $filter) {
continue;
}
echo $item, ' ';
}
This question already has answers here:
Displaying and Randomising php Arrays
(4 answers)
Closed 9 years ago.
How do i randomize my array elements and limit number of items to be displayed to 5
My code is:
while($row = mysql_fetch_assoc($result))
{
$new_array[] = $row;
}
echo '<pre>'; print_r(($new_array));
Easiest solution...
array_rand($array, 5);
PHP array_rand()
shuffle($array);
$pointer = 0;
foreach($array as $value) {
if($pointer > 4) break;
echo $value;
$pointer++
}
shuffle will randomize your array, then you start a pointer at 0 and increment it in your foreach loop, if you the pointer is more than 4 you break the foreach loop
as another solution, you could use a for loop
shuffle($array);
for($i = 0; $i < 5; $i++) {
echo $array[$i];
}
and one more solution for limiting, since you're pulling the array for your database by a query, you can limit the number of rows returned by a number you choose by adding LIMIT 5 at the end of your query.
This question already has answers here:
Get next element in foreach loop
(11 answers)
Closed 9 years ago.
I am looking for a way to get the next and next+1 key/value pair in a foreach(). For example:
$a = array('leg1'=>'LA', 'leg2'=>'NY', 'leg3'=>'NY', 'leg4'=>'FL');
foreach($a AS $k => $v){
if($nextval == $v && $nextnextval == $v){
//staying put for next two legs
}
}
You can't access that way the next and next-next values.
But you can do something similar:
$a = array('leg1'=>'LA', 'leg2'=>'NY', 'leg3'=>'NY', 'leg4'=>'FL');
$keys = array_keys($a);
foreach(array_keys($keys) AS $k ){
$this_value = $a[$keys[$k]];
$nextval = $a[$keys[$k+1]];
$nextnextval = $a[$keys[$k+2]];
if($nextval == $this_value && $nextnextval == $this_value){
//staying put for next two legs
}
}
I've found the solution with complexity O(n) and does not require seeking through array back and forward:
$a = array('leg1'=>'LA', 'leg2'=>'NY', 'leg3'=>'NY', 'leg4'=>'FL');
// initiate the iterator for "next_val":
$nextIterator = new ArrayIterator($a);
$nextIterator->rewind();
$nextIterator->next(); // put the initial pointer to 2nd position
// initiaite another iterator for "next_next_val":
$nextNextIterator = new ArrayIterator($a);
$nextNextIterator->rewind();
$nextNextIterator->next();
$nextNextIterator->next(); // put the initial pointer to 3rd position
foreach($a AS $k => $v){
$next_val = $nextIterator->current();
$next_next_val = $nextNextIterator->current();
echo "Current: $v; next: $next_val; next_next: $next_next_val" . PHP_EOL;
$nextIterator->next();
$nextNextIterator->next();
}
Just remember to test for valid() if you plan to relay on the $next_val and $next_next_val.
Here's one way to do it:
while($current = current($a)) {
$next = next($a);
$nextnext = next($a);
// Comparison logic here
prev($a); // Because we moved the pointer ahead twice, lets back it up once
}
Example: http://3v4l.org/IGCXW
Note that the loop written this way will never examine the last element in your original array. That could be fixed, although with your current logic it doesn't seem to matter since there are no "more" elements to compare the last one to.
Have a look at CachingIterator, as described in this answer:
Peek ahead when iterating an array in PHP
Or use array_keys() is in another answer posted for the same question, e.g.
$keys = array_keys($array);
for ($i = 0; $i < count($keys); $i++) {
$cur = $array[$keys[$i]];
$next = $array[$keys[$i+1]];
}
You can't simply "stay put" in a loop. I suspect you're looking to do something a lot easier than write custom iterators. If you simply want to ignore entries with duplicate keys, then track the last key and compare it to the current one.
$a = array('leg1'=>'LA', 'leg2'=>'NY', 'leg3'=>'NY', 'leg4'=>'FL');
// Prints LA NY FL
$last_v = null;
foreach ( $a as $k => $v ){
if ( $last_v == $v ) {
/**
* Duplicate value, so skip it
*/
continue;
}
echo $v.' ';
$last_v = $v;
}
Funny, I'm programming PHP for a decade (with years pause), but I needed one-by-one walk functions just a week ago.
Here you are: next, prev, reset etc. See "see also" section. Also, check array_keys()
this is my first php script and problem, I've searched hours with no conclusion other than looping a function" too many laterations". but it doesn't solve my problem I've never studied programming or what ever so I'm hoping that there is an educated person to fill me in on this:
I have an array that contains 120 elements; consists of duplicates eg:
myArray = [0]= item_1, [1] = item _1, [2] = item_2, [3] = item_3 ect..
Briefly I'm trying to make a flash php pokermachine but I need these items in the array to be shuffled BUT I do not want the duplicates to be next to each other after the shuffle but I need the duplicates to be still in the array
I can't do a loop function to check this because it will change the shuffle too many times which will effect the odds of the game: below is what I currently have:
/ * Removed the link here that is no longer available */
you may notice at times it will double up with 2 items in the same reel
Basically I created the virtual reel dynamically with php.ini file
these values are repeatedly pushed into an array($virtualreel) so the value may appear 10 times in the reel and another value will appear 5 times variating the odds. Then after I take a random slice() from the $virtualreel to display 3 vars from this reel and repeat the loop 4 more times for the other reels, also I only can shuffle once as I want the slice() to be from the same reels array order
I only shuffle every new spin not running loop functions to shuffle if I double up on a slice(array,3 items).
hope I've explained what I'm after well enough to give you guys an idea.
You can use this function:
<?php
function shuffleArray($myArray) {
$value_count = array_count_values($myArray);
foreach($value_count as $key=>$value) {
if ($value > count($myArray)/2) {
return false;
}
}
$last_value = $myArray[count($myArray) - 1];
unset($myArray[count($myArray) - 1]);
$shuffle = array();
$last = false;
while (count($myArray) > 0) {
$keys = array_keys($myArray);
$i = round(rand(0, count($keys) - 1));
while ($last === $myArray[$keys[$i]]) {
$i = round(rand(0, count($keys) - 1));
}
$shuffle[] = $myArray[$keys[$i]];
$last = $myArray[$keys[$i]];
unset($myArray[$keys[$i]]);
}
if ($last_value === $last) {
$i = 0;
foreach($shuffle as $key=>$value) {
if ($value !== $last_value) {
$i = $key;
break;
}
}
array_splice($shuffle, $i + 1, 0, $last_value);
} else {
$shuffle[] = $last_value;
}
return $shuffle;
}
print_r(shuffleArray(array(1,5,5,3,7,7)));
Why not just:
Edit :
$shuffled = array();
while(count($to_shuffle) > 0):
$i = rand(0, count($to_shuffle)-1);
$shuffled[] = $to_shuffle[$i];
array_splice($to_shuffle, $i, 1,null);
endwhile;
I think this is what you were expecting, if you don't mind not preserving the association between keys and values.
I have a database table with images that I need to display. In my view, I'd like to display UP TO 10 images for each result called up. I have set up an array with the 20 images that are available as a maximum for each result (some results will only have a few images, or even none at all). So I need a loop that tests to see if the array value is empty and if it is, to move onto the next value, until it gets 10 results, or it gets to the end of the array.
What I'm thinking I need to do is build myself a 2nd array out of the results of the test, and then use that array to execute a regular loop to display my images. Something like
<?php
$p=array($img1, $img2.....$img20);
for($i=0; $i<= count($p); $i++) {
if(!empty($i[$p])) {
...code
}
}
?>
How do I tell it to store the array values that aren't empty into a new array?
you could do something like:
$imgs = array(); $imgs_count = 0;
foreach ( $p as $img ) {
if ( !empty($img) ) {
$imgs[] = $img;
$imgs_count++;
}
if ( $imgs_count === 10 ) break;
}
You can simply call array_filter() to get only the non-empty elements from the array. array_filter() can take a callback function to determine what to remove, but in this case empty() will evaluate as FALSE and no callback is needed. Any value that evaluates empty() == TRUE will simply be removed.
$p=array($img1, $img2.....$img20);
$nonempty = array_filter($p);
// $nonempty contains only the non-empty elements.
// Now dow something with the non-empty array:
foreach ($nonempty as $value) {
something();
}
// Or use the first 10 values of $nonempty
// I don't like this solution much....
$i = 0;
foreach ($nonempty as $key=>$value) {
// do something with $nonempty[$key];
$i++;
if ($i >= 10) break;
}
// OR, it could be done with array_values() to make sequential array keys:
// This is a little nicer...
$nonempty = array_values($nonempty);
for ($i = 0; $i<10; $i++) {
// Bail out if we already read to the end...
if (!isset($nonempty[$i]) break;
// do something with $nonempty[$i]
}
$new_array[] = $p[$i];
Will store $p[$i] into the next element of $new_array (a.k.a array_push()).
Have you thought about limiting your results in the sql query?
select * from image where img != '' limit 10
This way you are always given up to 10 results that are not empty.
A ẁhile loop might be what you're looking for http://php.net/manual/en/control-structures.while.php