How can I accomplish this in php? there are cases where I need to push more elements to the array that i'm looping through so they also get looped through:
$j = array(1,2,3);
foreach ($j as $i)
{
echo $i . "\n";
if ($i <= 3)
array_push($j, 5);
}
should print 123555 but it stops at 123.
is there a way around this in php?
foreach works on a copy of the array, not the original array (under certain conditions). That's why you're not seeing the changed reflected in the loop.
You will get the expected output when you loop by reference:
foreach ($j as &$i)
{
// ...
}
Output:
1
2
3
5
5
5
Add & to pass the reference. Default a value (copy of $j) is passed.
$j = array(1,2,3);
foreach ($j as $i=>&$v)
{
echo "$i=>$v\n";
if ($i <= 3)
array_push($j, 5);
}
PHP does not support this. From the manual:
As foreach relies on the internal array pointer changing it within the loop may lead to unexpected behavior.
http://php.net/manual/en/control-structures.foreach.php
However, this code will work, although I would not rely on this based on what the manual said.
<?
header( 'content-type: text/plain' );
$j = array(1,2,3);
foreach ($j as &$v )
{
echo "$v\n";
if ($v <= 3)
{
array_push($j, 5);
}
}
Why don't you try while:
$i = 0;
$j = array( 1, 2, 3 );
while ( count( $j ) )
{
echo array_shift( $j );
if ( $i++ <= 3 )
{
array_push( $j, 5 );
}
}
Related
I have a multidimentional array of 5 items and I want that my loop would compare it like:
1 -> 2, 1 -> 3, 1 -> 4, 1 -> 5, 2->1, 2->3, 2->4, 2->5......// so on and 5 -> 4 in the end.
The problem is that after my array $i value matches 1 and $j value matches 3, the unset is done and the $i value becomes 2 (which is correct) and $j value becomes 4 instead of 3. Could someone tell me why and what I'm doing wrong?
My loop is:
for ($i = 0; $i <= count($myArray); $i++) {
for ($j = $i+1; $j <= count($myArray); $j++) {
if (
// condition 1
&& // condition 2
) {
unset($myArray[$i]);
$i++;
}
}
}
I think that's the problem is when you unset the element in the array, you increment the counter of the loop $i. In this way, the elements of the array that are not configured are removed, this empty array position will be maintained, it will not be reordered, you will have to do it manually or using array_values method.
In the last tour of the array, it will break because you are comparing the number of array elements as equal. You must use index < count($array)
The code would be like this:
for ($i = 0; $i < count($myArray); $i++) {
for ($j = $i+1; $j < count($myArray); $j++) {
if (
// condition 1
&& // condition 2
) {
unset($myArray[$i]);
// $i++;
}
}
}
try something like this
for ($i = 0; $i <= count($myArray); $i++) {
for ($j = 0; $j <= count($myArray); $j++) {
if ($j!=$i)
{
if (
// condition 1
&& // condition 2
) {
unset($myArray[$i]);
$i++;
}
}
}
}
$temp = $myArray;
for ($i = 0; $i <= count($myArray); $i++)
{
for ($j = $i + 1; $j <= count($myArray); $j++)
{
if (
// condition 1
&& // condition 2
)
{
unset($temp[$i]);
$i++;
}
}
}
print_r($temp);
Your result is in $temp. So here indexes wont get hampered, you actually are applying all operation on $temp and normally traversing $myArray.
To be honest, I do not know why nobody has yet advise to use nested foreach, since you all noticed there was a problem with array size.
foreach ($numbers as $number_horizontal_parsing) {
foreach ($numbers as $number_vertical_parsing) {
if ($number_horizontal_parsing != $number_vertical_parsing) {
//do your stuff in your case it seems you want to compare both variables
}
}
}
Here is my code, and it is not removing $arr[5] element so that I am trying to remove strings starting with # from my array
this is code
<?php
$arr = [
'#EXTM3U',
'#EXTINF:177,Paul Dateh & Oren Yoel - Be More',
'Be More.mp3',
'#EXTINF:291,Christopher Toy - Just Because',
'Just Because.mp3',
'#EXTINF:238,Magnetic North - Drift Away',
'Drift Away.mp3'
];
for ($i = 0; $i <= count($arr); $i++) {
if ($arr[$i]{0} == '#') {
echo $arr[$i] . "\n";
unset($arr[$i]);
}
}
print_r($arr);
?>
Reason:- You are counting array length inside the loop and every time when any value got unset() from the array, length of array decreased and value of count($array) changed (simply decreased)
So logically your 5th and 6th element never goes through if condition (they never get traversed by loop because of decreasing length of the array )
Solution 1:- Put count outside and it will work properly:-
$count = count($arr);
//loop start from 0 so use < only otherwise, sometime you will get an undefined index error
for ($i = 0; $i < $count; $i++) {
if ($arr[$i]{0} == '#') {
//echo $arr[$i] . "\n";
unset($arr[$i]);
}
}
print_r($arr);
Output:-https://eval.in/996494
Solution 2:- That's why i prefer foreach() over for() loop
foreach($arr as $key=> $ar){
if ($ar[0] == '#') {
unset($arr[$key]);
}
}
print_r($arr);
Output:-https://eval.in/996502
more spacific :
for ($i = 0; $i < count($arr); $i++) {
if (strpos($arr[$i], '#') !== false) {
echo "<br/>";
} else {
echo $arr[$i]."<br/>";
}
}
Try to use additional array to push right values. You calc count($arr); each iteration and when you do count($arr); your array gets smaller and count($arr); returns smaller values, so last elements won't be comparing, try to use variable to calc count before loop make changes:
<?php
//...
$start_count = count($arr);
for ($i = 0; $i <= $start_count; $i++) {
if ($arr[$i]{0} == '#') {
echo $arr[$i] . "\n";
unset($arr[$i]);
}
}
Or remove bad element with a help of additional array, put good elements in new array and don't delete them from input array:
<?php
$arr = [
'#EXTM3U',
'#EXTINF:177,Paul Dateh & Oren Yoel - Be More',
'Be More.mp3',
'#EXTINF:291,Christopher Toy - Just Because',
'Just Because.mp3',
'#EXTINF:238,Magnetic North - Drift Away',
'Drift Away.mp3'
];
$cleared_from_mess_array = array();
for ($i = 0; $i <= count($arr); $i++) {
if ($arr[$i]{0} != '#')
{
array_push($cleared_from_mess_array,$arr[$i]);
}
}
print_r($cleared_from_mess_array);
exit;
I am trying to remove duplicates from a set of tokens using unset (not considering array_unique for now), however I am getting a few issues.
$keywords = parseTweet ( $tweet );
$term_freq = array(count($keywords));
for($i = 0; $i < count($keywords); $i++){
$term_freq[$i] = 1;
for($j = 0; $j < count($keywords); $j++){
if (($i != $j) && (strcmp($keywords[$i],$keywords[$j]) == 0)){
unset ( $keywords [$j] );
unset ( $term_freq [$j] );
$term_freq[$i]++;
}
}
}
print_r ( $keywords );
print_r ( $term_freq );
I am aware of why I am getting an error; while the duplicate $j is removed, the for loop still has to reloop for the rest of the keywords and hence will fail when it encounters the missing $j. Checking the contents of the array, I found out that the index of the array skips the index $j. So it reads; [1], [2], [4], ... etc where $j = [3]
I thought that unset also rebalances the array index, am I doing something wrong or missing something completely? I am new to PHP so please bear with me!
Check if the index is set or not.
You're making needless, repetitive comparisons. Basically n² comparisons when at most n²/2 are required to compare every value in an array to every other value.
So:
$c = count($keywords)
for($i = 0; $i < $c; $i++){
$term_freq[$i] = 1;
for($j = $i+1; $j < $c; $j++){ // magic is $j = $i+1
if( ! isset($keywords[$j]) { continue; } // skip unset indices
else if ( strcmp($keywords[$i],$keywords[$j]) == 0 ){
unset ( $keywords [$j] );
unset ( $term_freq [$j] );
$term_freq[$i]++;
}
}
}
Basically you know you've already checked everything prior to $i, so you can start your inner loop at $i+1 instead of zero.
Also, you only need to count $keywords once, not n² times.
Use foreach instead of for.
foreach ($keywords as $i => $kw1){
$term_freq[$i] = 1;
foreach ($keywords as $j => $kw2){
if (($i != $j) && ($kw1 == $kw2){
unset ( $keywords [$j] );
unset ( $term_freq [$j] );
$term_freq[$i]++;
}
}
}
I have an array in php, and I want to print the elements of the array, 15 at a time, from (n-15). Like, if I have 100 elements in an array, I want to print it 85-100,70-84,55-70,, etc.,
I've tried the loop
for( $j = sizeof($fields)-16; $j < sizeof($fields); ) {
for ( $i = $j ; $i < $i+16 ; $i++ ) {
echo $fields[$i];
echo "<br>";
}
$j=$j-16;
}
but, this prints only the first iternation, i.e 85-100, and goes into an infinite loop.
Where am i going wrong?
Help!
foreach (array_reverse(array_chunk($fields, 15)) as $chunk) {
foreach ($chunk as $field) {
echo $field . '<br />';
}
}
In PHP 5.3, you can do this:
<?php
$fields = range(1, 100);
foreach (array_chunk(array_reverse($fields, true), 15, true) as $i => $chunk) {
echo 'Group ' . $i . ":<br/>\n";
$chunk_rev = array_reverse($chunk, true);
array_walk($chunk_rev, function($value) {
echo "$value<br/>\n";
});
}
See the demo.
Think about the loop termination condition.
If $j is being decremented and $j starts off lower than the comparison value, $j will never be greater than the comparison value, so the loop will never terminate.
I've got a problem. In my opinion this should work fine:
for($i = 0; $i < count($tags); $i++){
if(in_array($tags[$i], $str)){
for($a = 0; $a < count($str); $a++){
if($tags[$i] == $str[$a]){
unset($str[$a]);
}
}
}
}
str is an array consisting of 1, 3, 4, 5, 500, 501.
tags is an array consisting of 4, 5, 500, 501.
The result should be 1, 3. The result is 1, 3, 500, 501.
After experimenting, I found out that this code works but is unstable, in my opinion:
for($i = 0; $i < count($str) + count($tags); $i++){
for($a = 0; $a < count($tags); $a++){
if ($tags[$a] == $str[$i]) {
unset($str[$i]);
}
}
$a = 0;
}
What am I doing wrong?
Far too much code, when you could simply do:
$difference = array_diff($tags, $str);
Assuming that you're not using array_diff.
Unless you have an extremely compelling reason, foreach is simply better. You don't need count and you're dealing with the actual keys of the array.
The built in array functions are your friends. array_search is far better at iterating than the most optimized PHP code.
While loops can make your life better :-)
Example:
foreach( $tags as $tag )
{
while( ( $key = array_search( $tag, $str ) ) !== FALSE )
{
unset( $str[ $key ] );
}
}