I have associative array such as:
$myArray = array(
'key1' => 'val 1',
'key2' => 'val 2'
...
);
I do not know the key values up front but want to start looping from the second element. In the example above, that would be from key2 onwards.
I tried
foreach(next(myArray) as $el) {
}
but that didnt work.
Alternatives may be array_slice but that seems messy. Am i missing something obvious?
There really is no "one true way" of doing this. So I'll take it as a benchmark as to where you should go.
All information is based on this array.
$array = array(
1 => 'First',
2 => 'Second',
3 => 'Third',
4 => 'Fourth',
5 => 'Fifth'
);
The array_slice() option. You said you thought this option was overkill, but it seems to me to be the shortest on code.
foreach (array_slice($array, 1) as $key => $val)
{
echo $key . ' ' . $val . PHP_EOL;
}
Doing this 1000 times takes 0.015888 seconds.
There is the array functions that handle the pointer, such as ...
current() - Return the current element in an array.
end() - Set the internal pointer of an array to its last element.
prev() - Rewind the internal array pointer.
reset() - Set the internal pointer of an array to its first element.
each() - Return the current key and value pair from an array and advance the array cursor.
Please note that the each() function has been deprecated as of PHP 7.2, and will be removed in PHP 8.
These functions give you the fastest solution possible, over 1000 iterations.
reset($array);
while (next($array) !== FALSE)
{
echo key($array) . ' ' . current($array) . PHP_EOL;
}
Doing this 1000 times, takes 0.014807 seconds.
Set a variable option.
$first = FALSE;
foreach ($array as $key => $val)
{
if ($first != TRUE)
{
$first = TRUE;
continue;
}
echo $key . ' ' . $val . PHP_EOL;
}
Doing this 1000 times takes 0.01635 seconds.
I rejected the array_shift options because it edits your array and you've never said that was acceptable.
This depends on whether you want to do this just once or many times, and on whether you still need the original array later on.
"First" pattern
$first = true;
foreach ($array as $key=>value) {
if($first) {
$first = false;
continue;
}
// ... more code ...
}
I personally use this solution quite often because it's really straight-forward, everybody gets this. Also, there is no performance hit of creating a new array and you can still operate on the original array after the loop.
However, if you have a couple of loops like this, it kind of starts looking a little unclean, because you need 5 extra lines of code per loop.
array_shift
array_shift($array);
foreach ($array as $key=>value) {
// .... more code ....
}
array_shift is a function tailored to this special case of not wanting the first element. Essentially it's a Perl-ish way of saying $array = array_slice($array, 1) which might not be completely obvious, especially since it modifies the original array.
So, you might want to make a copy of the original array and shift it, if you need both the shifted array multiple times and also the original array later on.
array_slice
And, of course, there is array_slice itself. I don't see anything wrong with array_slice if you want the original array to remain unchanged and you need the sliced array multiple times. However, if you're positive that you always want to slice just one element off, you might as well use the shorthand array_shift (and make a copy before if needed).
You can go with the obvious way:
$flag = false;
foreach($myArray as $el) {
if($flag) {
// do what you want
}
$flag = true;
}
Just another way of flexible iteration:
reset($myArray); // set array pointer to the first element
next($myArray); // skip first element
while (key($myArray) !== null) {
// do something with current($myArray)
next($myArray);
}
As far as I know foreach is just a kind of shortcut for this construction.
From Zend PHP 5 Certication study guide:
As you can see, using this set of functions [reset, next, key,
current, ...] requires quite a bit of work; to be fair, there are some
situations where they offer the only reasonable way of iterating
through an array, particularly if you need to skip back-and-forth
between its elements. If, however, all you need to do is iterate
through the entire array from start to finish, PHP provides a handy
shortcut in the form of the foreach() construct.
If your array was 0 based, it would be if($key>=1), but as your array starts at key 1, then this should work.
foreach ($array as $key=>$value){if($key>=2){
do stuff
}}
You could try:
$temp = array_shift($arr);
foreach($arr as $val) {
// do something
}
array_unshift($arr, $temp);
reset($myArray);
next($myArray);
while ($element = each($myArray))
{
//$element['key'] and $element['value'] can be used
}
My fairly simple solution when this issue pops up. It has the nice advantage of being easily being modified to be able to skip more than just the first element if you want it to.
$doomcounter = 0;
foreach ($doomsdayDevice as $timer){ if($doomcounter == 0){$doomcounter++; continue;}
// fun code goes here
}
Related
I have a foreach loop like below code :
foreach($coupons as $k=>$c ){
//...
}
now, I would like to fetch two values in every loop .
for example :
first loop: 0,1
second loop: 2,3
third loop: 4,5
how can I do ?
Split array into chunks of size 2:
$chunks = array_chunk($coupons, 2);
foreach ($chunks as $chunk) {
if (2 == sizeof($chunk)) {
echo $chunk[0] . ',' . $chunk[1];
} else {
// if last chunk contains one element
echo $chunk[0];
}
}
If you want to preserve keys - use third parameter as true:
$chunks = array_chunk($coupons, 2, true);
print_r($chunks);
Why you don't use for loop like this :
$length = count($collection);
for($i = 0; $i < $length ; i+=2)
{
// Do something
}
First, I'm making the assumption you are not using PHP 7.
It is possible to do this however, it is highly, highly discouraged and will likely result in unexpected behavior within the loop. Writing a standard for-loop as suggested by #Rizier123 would be better.
Assuming you really want to do this, here's how:
Within any loop, PHP keeps an internal pointer to the iterable. You can change this pointer.
foreach($coupons as $k=>$c ){
// $k represents the current element
next($coupons); // move the internal array pointer by 1 space
$nextK = current($coupons);
prev($coupons);
}
For more details, look at the docs for the internal array pointer.
Again, as per the docs for foreach (emphasis mine):
Note: In PHP 5, when foreach first starts executing, the internal array pointer is automatically reset to the first element of the
array. This means that you do not need to call reset() before a
foreach loop. As foreach relies on the internal array pointer in PHP
5, changing it within the loop may lead to unexpected behavior. In PHP
7, foreach does not use the internal array pointer.
Let's assume your array is something like $a below:
$a = [
"a"=>1,
"b"=>2,
"c"=>3,
"d"=>4,
"e"=>5,
"f"=>6,
"g"=>7,
"h"=>8,
"i"=>9
];
$b = array_chunk($a,2,true);
foreach ($b as $key=>$value) {
echo implode(',',$value) . '<br>';
}
First we split array into chunks (the parameter true preserves the keys) and then we do a foreach loop. Thanks to the use of implode(), you do not need a conditional statement.
well this'd be 1 way of doing it:
$keys=array_keys($coupons);
for($i=0;$i<count($keys);++$i){
$current=$coupons[$keys[$i]];
$next=(isset($keys[$i+1])?$coupons[$keys[$i+1]]:NULL);
}
now the current value is in $current and the next value is in $next and the current key is in $keys[$i] and the next key is in $keys[$i+1] , and so on.
As a php beginner, I meet a problem with calculating the elements of array in php
$effect=array("a"=>array(1,2),"b"=>array(1,2),"c"=>array(1,2));
I just want to make the result as this
$effect['a'][0]=$effect['a'][0]/$effect['a'][1];
$effect['b'][0]=$effect['b'][0]/$effect['b'][1];
$effect['c'][0]=$effect['c'][0]/$effect['c'][1];
Except do this one by one , How to do this calculation with foreach or other loop way
Your array syntax is a bit off. It should be $effect['a'][0].
The loop is trivial, and foreach was the right idea.
You can use it to iterate over all the letters using:
foreach ($effect as $letter => $numbers) {
...
}
Then put your assignment/division line in the loop, replacing the fixed 'a' and 'b' etc. with the $letter variable.
You need something like this?
foreach ($effect as $key => $val)
{
$results[$key] = $val[0] / $val[1];
}
print_r($results);
Also one counter-intuitive thing in PHP, is that arrays are passed by value by default. You can use & to get a reference to the array
$effects =array("a"=>array(1,2),"b"=>array(1,2),"c"=>array(1,2));
foreach ( $effects as $key => &$effect ) {
$effect[0] = $effect[0]/$effect[1];
unset($effect);
}
print_r( $effects );
See this:
$q = 'blah';
for($k = 0; $k < count($results_array); $k++){
$results_array_ . $k = explode(',', $results_array[$k]);
foreach($results_array_ . $k as $key => $value){
if (stripos($value, $q) === false) {
unset($results_array_ . $k[$key]);
break;
}
}
}
On line 3 I'm simply using "$results_array_ . $k" and it's working just fine, but on line 6 I'm getting PHP parse errors on "unset($results_array_ . $k[$key])", why is this happening?
I appreciate anykind of help
Why I'm doing it:
I have an array named results_array:
var_dump($results_array):
0 => php,mysql,jquery,ruby,html,css,lamp
1 => mouse,keyboard,laptop,pad
2 => table,sofa,caption
and I have a $q which stands for query, I want to search in the $results_array and remove the items which has nothing to do with the query, so if I set $q=a then results array should be this:
0 => lamp
1 => keyboard,laptop,pad
3 => table,sofa,caption
now, I want to put the above results in each index of the results_array, at the end results_array should be:
0 => lamp
1 => keyboard
2 => laptop
3 => pad
4 => table
5 => sofa
6 => caption
Answer to original question
unset expects its argument to be a direct reference to a value, e.g. $var or $array['key']. If you want to dynamically create the argument based on other values, you 'll have to use variable variable syntax:
unset(${$results_array_ . $k[$key]});
This will get rid of the warning, but it still won't make the code work because it's fundamentally flawed. Line 3 which you mention reads:
$results_array_ . $k = explode(',', $results_array[$k]);
What this does is explode an array into $k and then concatenate $results_array_ with $k and... throw away the result. You could just as easily have written
$k = explode(',', $results_array[$k]);
and it would work the same (except possibly not giving an E_NOTICE that $_results_array_ does not exist).
So, it seems that you have a misunderstanding of how some PHP fundamentals work. It would be best if you asked another question that explains what you are trying to do, in order to determine what would be a good way of doing it.
Answer to current question
Let's take the steps one at a time:
Take the array of strings and turn each string into an array with explode, making an array of arrays. You can do this with array_map or a simple foreach.
"Flatten" the array of arrays into one big array. You can do this with array_merge or array_merge_recursive (the details will be a bit different, the idea is the same).
Search the flattened array and filter out uninteresting elements with array_filter.
If necessary, reindex the filtered array so that it has consecutive numeric keys with array_values.
Here's code that does this, albeit a little differently (I am doing steps 1 and 2 at the same time in the first line using array_reduce):
$array = (...);
$array = array_reduce($array, function(&$result, $item) {
return array_merge($result, explode(',', $item));
}, array());
$array = array_filter($array, function($item) use ($string) {
return strpos($item, $string) !== false;
});
$result = array_values($array);
A version that does the same without using fancy functions:
// Step 1
foreach($array as &$row) {
$row = explode(',', $row);
}
unset($row);
// Step 2
$array = call_user_func_array('array_merge_recursive', $array);
// Step 3
foreach ($array as $k => $v) {
if(strpos($v, 'a') === false) unset($array[$k]);
}
// Step 4
$array = array_values($array);
I am writing a foreach that does not start at the 0th index but instead starts at the first index of my array. Is there any way to offset the loop's starting point?
Keep it simple.
foreach ($arr as $k => $v) {
if ($k < 1) continue;
// your code here.
}
See the continue control structure in the manual.
A Foreach will reset the array:
Note: When foreach first starts executing, the internal array pointer is automatically reset to the first element of the array. This means that you do not need to call reset() before a foreach loop.
Either use a for loop (only if this is not an associative array)
$letters = range('a','z');
for($offset=1; $offset < count($letters); $offset++) {
echo $letters[$offset];
}
or a while loop (can be any array)
$letters = range('a','z');
next($letters);
while($letter = each($letters)) {
echo $letter['value'];
}
or with a LimitIterator
$letters = new LimitIterator(new ArrayIterator(range('a','z')), 1);
foreach($letters as $letter) {
echo $letter;
}
which lets you specify start offset and count through the constructor.
All of the above will output the letters b to z instead of a to z
You can use the array_slice function:
$arr = array(); // your array
foreach(array_slice($arr, 1) as $foo){
// do what ever you want here
}
Of course, you can use whatever offset value you want. In this case, 1 'skip' the first element of the array.
In a foreach you cant do that. There are only two ways to get what you want:
Use a for loop and start at position 1
use a foreach and use a something like if($key>0) around your actual code
A foreach does what its name is telling you. Doing something for every element :)
EDIT: OK, a very evil solution came just to my mind. Try the following:
foreach(array_reverse(array_pop(array_reverse($array))) as $key => $value){
...
}
That would reverse the array, pop out the last element and reverse it again. Than you'll have a element excluding the first one.
But I would recommend to use one of the other solutions. The best would be the first one.
And a variation: You can use array_slice() for that:
foreach(array_slice($array, 1, null, true) as $key => $value){
...
}
But you should use all three parameters to keep the keys of the array for your foreach loop:
Seems like a for loop would be the better way to go here, but if you think you MUST use foreach you could shift the first element off the array and unshift it back on:
$a = array('foo','bar');
$temp = array_shift($a);
foreach ( $a as $k => $v ) {
//do something
}
array_unshift($a, $temp);
Well no body said it but if you don't mind altering the array and if we want to start from the second element of the given array:
unset($array[key($array)]);
foreach($array as $key=>$value)
{
//do whatever
}
if you do mind, just add,
$saved = $array;
unset($array[key($array)]);
foreach($array as $key=>$value)
{
//do whatever
}
$array = $saved;
Moreover if you want to skip a given known index, just subtitute
key($array)
by the given index
bismillah...
its simple just make own keys
$keys=1;
foreach ($namafile_doc as $value ) {
$data['doc'.$keys]=$value;
$keys++;
}
may this answer can make usefull
If I had an array like:
$array['foo'] = 400;
$array['bar'] = 'xyz';
And I wanted to get the first item out of that array without knowing the key for it, how would I do that? Is there a function for this?
reset() gives you the first value of the array if you have an element inside the array:
$value = reset($array);
It also gives you FALSE in case the array is empty.
PHP < 7.3
If you don't know enough about the array (you're not sure whether the first key is foo or bar) then the array might well also be, maybe, empty.
So it would be best to check, especially if there is the chance that the returned value might be the boolean FALSE:
$value = empty($arr) ? $default : reset($arr);
The above code uses reset and so has side effects (it resets the internal pointer of the array), so you might prefer using array_slice to quickly access a copy of the first element of the array:
$value = $default;
foreach(array_slice($arr, 0, 1) as $value);
Assuming you want to get both the key and the value separately, you need to add the fourth parameter to array_slice:
foreach(array_slice($arr, 0, 1, true) as $key => $value);
To get the first item as a pair (key => value):
$item = array_slice($arr, 0, 1, true);
Simple modification to get the last item, key and value separately:
foreach(array_slice($arr, -1, 1, true) as $key => $value);
performance
If the array is not really big, you don't actually need array_slice and can rather get a copy of the whole keys array, then get the first item:
$key = count($arr) ? array_keys($arr)[0] : null;
If you have a very big array, though, the call to array_keys will require significant time and memory more than array_slice (both functions walk the array, but the latter terminates as soon as it has gathered the required number of items - which is one).
A notable exception is when you have the first key which points to a very large and convoluted object. In that case array_slice will duplicate that first large object, while array_keys will only grab the keys.
PHP 7.3+
PHP 7.3 onwards implements array_key_first() as well as array_key_last(). These are explicitly provided to access first and last keys efficiently without resetting the array's internal state as a side effect.
So since PHP 7.3 the first value of $array may be accessed with
$array[array_key_first($array)];
You still had better check that the array is not empty though, or you will get an error:
$firstKey = array_key_first($array);
if (null === $firstKey) {
$value = "Array is empty"; // An error should be handled here
} else {
$value = $array[$firstKey];
}
Fake loop that breaks on the first iteration:
$key = $value = NULL;
foreach ($array as $key => $value) {
break;
}
echo "$key = $value\n";
Or use each() (warning: deprecated as of PHP 7.2.0):
reset($array);
list($key, $value) = each($array);
echo "$key = $value\n";
There's a few options. array_shift() will return the first element, but it will also remove the first element from the array.
$first = array_shift($array);
current() will return the value of the array that its internal memory pointer is pointing to, which is the first element by default.
$first = current($array);
If you want to make sure that it is pointing to the first element, you can always use reset().
reset($array);
$first = current($array);
another easy and simple way to do it use array_values
array_values($array)[0]
Just so that we have some other options: reset($arr); good enough if you're not trying to keep the array pointer in place, and with very large arrays it incurs an minimal amount of overhead. That said, there are some problems with it:
$arr = array(1,2);
current($arr); // 1
next($arr); // 2
current($arr); // 2
reset($arr); // 1
current($arr); // 1 !This was 2 before! We've changed the array's pointer.
The way to do this without changing the pointer:
$arr[reset(array_keys($arr))]; // OR
reset(array_values($arr));
The benefit of $arr[reset(array_keys($arr))]; is that it raises an warning if the array is actually empty.
Test if the a variable is an array before getting the first element. When dynamically creating the array if it is set to null you get an error.
For Example:
if(is_array($array))
{
reset($array);
$first = key($array);
}
We can do
$first = reset($array);
Instead of
reset($array);
$first = current($array);
As reset()
returns the first element of the array after reset;
You can make:
$values = array_values($array);
echo $values[0];
Use reset() function to get the first item out of that array without knowing the key for it like this.
$value = array('foo' => 400, 'bar' => 'xyz');
echo reset($value);
output //
400
Starting with PHP 7.3.0 it's possible to do without resetting the internal pointer. You would use array_key_first. If you're sure that your array has values it in then you can just do:
$first = $array[array_key_first($array)];
More likely, you'll want to handle the case where the array is empty:
$first = (empty($array)) ? $default : $array[array_key_first($array)];
You can try this.
To get first value of the array :-
<?php
$large_array = array('foo' => 'bar', 'hello' => 'world');
var_dump(current($large_array));
?>
To get the first key of the array
<?php
$large_array = array('foo' => 'bar', 'hello' => 'world');
$large_array_keys = array_keys($large_array);
var_dump(array_shift($large_array_keys));
?>
In one line:
$array['foo'] = 400;
$array['bar'] = 'xyz';
echo 'First value= ' . $array[array_keys($array)[0]];
Expanded:
$keys = array_keys($array);
$key = $keys[0];
$value = $array[$key];
echo 'First value = ' . $value;
You could use array_values
$firstValue = array_values($array)[0];
You could use array_shift
I do this to get the first and last value. This works with more values too.
$a = array(
'foo' => 400,
'bar' => 'xyz',
);
$first = current($a); //400
$last = end($a); //xyz