Targeting last child in PHP array within foreach - php

I am trying to target the last child of an array (within a foreach statement) to enable me to slightly adjust the output of just this item. I have tried numerous approaches but not having any breakthroughs. My loop is very simple:
// Loop through the items
foreach( $array as $item ):
echo $item;
endforeach;
The above works fine, but I want to change the output of the final item in the array to something like:
// Change final item
echo $item . 'last item';
Is this possible?

$last_key = end(array_keys($array));
foreach ($array as $key => $item) {
if ($key == $last_key) {
// last item
echo $item . 'last item';
}
}

Use count(), this will count all elements of your array. Use the length of the count for your last element index. as below. Set the last element as "Last Item" before your start your foreach this way you wont need no validation.
$array[count($array) - 1] = $array[count($array) - 1]."Last item";
foreach( $array as $item ){
echo $item;
}

It sounds like you want something like this:
<?php
// PHP program to get first and
// last iteration
// Declare an array and initialize it
$myarray = array( 1, 2, 3, 4, 5, 6 );
// Declare a counter variable and
// initialize it with 0
$counter = 0;
// Loop starts from here
foreach ($myarray as $item) {
if( $counter == count( $myarray ) - 1) {
// Print the array content
print( $item );
print(": Last iteration");
}
$counter = $counter + 1;
}
?>
Result Here

You can use end
end : Set the internal pointer of an array to its last element
$fruits = array('apple', 'banana', 'cranberry');
echo end($fruits); // cranberry

Hey you can simply use end function for the last element. You don't need to iterate it.
Syntax : end($array)

Related

Know the count of for-each loop before executing that loop

How may i know that - In php how many times the foreach loop will get run, before that loop get executed..In other words i want to know the count of that particular loop. I want to apply some different css depends upon the count.
Use the function count to get the amount of numbers in your array.
Example:
$array = array('test1', 'test2');
echo count($array); // Echos '2'
Or if you want to be an engineer for-sorts you can set up something like so:
$array = array('test1', 'test2');
$count = 0;
foreach ($array as $a) { $count++; }
And that can count it for you, and the $count variable will hold the count, hope this helped you.
Simply count() the array and use the output as a condition, like:
if (count($array) > 100) {
// This is an array with more than 100 items, go for plan A
$class = 'large';
} else {
// This is an array with less than 100 items, go for plan B
$class = 'small';
}
foreach ($array as $key => $value) {
echo sprintf('<div id="%s" class="%s">%s</div>', $key, $class, $value);
}

Finding the first, last and nth row in a foreach loop

I was wondering if PHP has a gracefull method to find the first, last and/or nth row in a foreach loop.
I could do it using a counter as follows:
$i = 0;
$last = count($array)-1;
foreach ($array as $key => $row) {
if ($i == 0) {
// First row
}
if ($i == $last) {
// Last row
}
$i++;
}
But somehow this feels like a bit of a dirty fix. Any solutions or suggestions?
Edit
As suggested in the comments I moved the count($array) outside the loop.
foreach ($array as $key => $row) {
$index = array_search($key, array_keys($array));
if ($index == 0) {
// First row
}
if ($index == count($array) - 1) {
// Last row
}
}
In php we have current and end function to get first and last value of array.
<?php
$transport = array('foot', 'bike', 'car', 'plane');
echo $first = current($transport); // 'foot';
echo $end = end($transport); // 'plane';
?>
Modified :
Easy way without using current or end or foreach loop:
$last = count($transport) - 1;
echo "First : $transport[0]";
echo "</br>";
echo "Last : $transport[$last]";
Using Arrays
For the first element in an array you can simply seek $array[0];. Depending on the array cursor you can also use current($array);
For the middle of an array you can use a combination of array_search() and array_keys().
For the end of an array you can use end($array); noting that this aslso moves the array cursor to the last element as well (as opposed to simply returning the value).
Using Iterators
However ArrayIterator's may also work well in your case:
The first element is available at ArrayIterator::current(); once constructed. (If you're halfway through the iterator you'll need to reset().)
For the n'th or a middle element you can use an undocumented Iterator::seek($index); method.
For the last element you can use a combination of seek() and count().
For example:
$array = array('frank' => 'one',
'susan' => 'two',
'ahmed' => 'three');
$arrayobject = new ArrayObject($array);
$iterator = $arrayobject->getIterator();
// First:
echo $iterator->current() . PHP_EOL;
// n'th: (taken from the documentation)
if($iterator->valid()){
$iterator->seek(1); // expected: two, output: two
echo $iterator->current() . PHP_EOL; // two
}
// last:
$iterator->seek(count($iterator)-1);
echo $iterator->current() . PHP_EOL;
$arr = ["A", "B", "C", "D", "E"];
reset($arr);
// Get First Value From Array
echo current($arr);
// Get Last Value From Array
echo end($arr);
Visit below link for details of above used functions.
reset() : http://php.net/manual/en/function.reset.php
current() : http://php.net/manual/en/function.current.php
end() : http://php.net/manual/en/function.end.php

Passing two variables into a 'foreach' loop

I need help regarding a foreach() loop. aCan I pass two variables into one foreach loop?
For example,
foreach($specs as $name, $material as $mat)
{
echo $name;
echo $mat;
}
Here, $specs and $material are nothing but an array in which I am storing some specification and material name and want to print them one by one. I am getting the following error after running:
Parse error: syntax error, unexpected ',', expecting ')' on foreach line.
In the Beginning, was the For Loop:
$n = sizeof($name);
for ($i=0; i < $n; $i++) {
echo $name[$i];
echo $mat[$i];
}
You can not have two arrays in a foreach loop like that, but you can use array_combine to combine an array and later just print it out:
$arraye = array_combine($name, $material);
foreach ($arraye as $k=> $a) {
echo $k. ' '. $a ;
}
Output:
first 112
second 332
But if any of the names don't have material then you must have an empty/null value in it, otherwise there is no way that you can sure which material belongs to which name. So I think you should have an array like:
$name = array('amy','john','morris','rahul');
$material = array('1w','4fr',null,'ff');
Now you can just
if (count($name) == count($material)) {
for ($i=0; $i < $count($name); $i++) {
echo $name[$i];
echo $material[$i];
}
Just FYI: If you want to have multiple arrays in foreach, you can use list:
foreach ($array as list($arr1, $arr2)) {...}
Though first you need to do this: $array = array($specs,$material)
<?php
$abc = array('first','second');
$add = array('112','332');
$array = array($abc,$add);
foreach ($array as list($arr1, $arr2)) {
echo $arr1;
echo $arr2;
}
The output will be:
first
second
112
332
And still I don't think it will serve your exact purpose, because it goes through the first array and then the second array.
You can use the MultipleIterator of SPL. It's a bit verbose for this simple use case, but works well with all edge cases:
$iterator = new MultipleIterator();
$iterator->attachIterator(new ArrayIterator($specs));
$iterator->attachIterator(new ArrayIterator($material));
foreach ($iterator as $current) {
$name = $current[0];
$mat = $current[1];
}
The default settings of the iterator are that it stops as soon as one of the arrays has no more elements and that you can access the current elements with a numeric key, in the order that the iterators have been attached ($current[0] and $current[1]).
Examples for the different settings can be found in the constructor documentation.
This is one of the ways to do this:
foreach ($specs as $k => $name) {
assert(isset($material[$k]));
$mat = $material[$k];
}
If you have ['foo', 'bar'] and [2 => 'mat1', 3 => 'mat2'] then this approach won't work but you can use array_values to discard keys first.
Another apprach would be (which is very close to what you wanted, in fact):
while ((list($name) = each($specs)) && (list($mat) = each($material))) {
}
This will terminate when one of them ends and will work if they are not indexed the same. However, if they are supposed to be indexed the same then perhaps the solution above is better. Hard to say in general.
Do it using a for loop...
Check it below:
<?php
$specs = array('a', 'b', 'c', 'd');
$material = array('x', 'y', 'z');
$count = count($specs) > count($material) ? count($specs) : count($material);
for ($i=0;$i<$count;$i++ )
{
if (isset($specs[$i]))
echo $specs[$i];
if (isset($material[$i]))
echo $material[$i];
}
?>
OUTPUT
axbyczd
Simply use a for loop. And inside that loop, extract values of your array:
For (I=0 to 100) {
Echo array1[i];
Echo array2[i]
}

how to skip elements in foreach loop

I want to skip some records in a foreach loop.
For example, there are 68 records in the loop. How can I skip 20 records and start from record #21?
Five solutions come to mind:
Double addressing via array_keys
The problem with for loops is that the keys may be strings or not continues numbers therefore you must use "double addressing" (or "table lookup", call it whatever you want) and access the array via an array of it's keys.
// Initialize 25 items
$array = range( 1, 25, 1);
// You need to get array keys because it may be associative array
// Or it it will contain keys 0,1,2,5,6...
// If you have indexes staring from zero and continuous (eg. from db->fetch_all)
// you can just omit this
$keys = array_keys($array);
for( $i = 21; $i < 25; $i++){
echo $array[ $keys[ $i]] . "\n";
// echo $array[$i] . "\n"; // with continuous numeric keys
}
Skipping records with foreach
I don't believe that this is a good way to do this (except the case that you have LARGE arrays and slicing it or generating array of keys would use large amount of memory, which 68 is definitively not), but maybe it'll work: :)
$i = 0;
foreach( $array as $key => $item){
if( $i++ < 21){
continue;
}
echo $item . "\n";
}
Using array slice to get sub part or array
Just get piece of array and use it in normal foreach loop.
$sub = array_slice( $array, 21, null, true);
foreach( $sub as $key => $item){
echo $item . "\n";
}
Using next()
If you could set up internal array pointer to 21 (let's say in previous foreach loop with break inside, $array[21] doesn't work, I've checked :P) you could do this (won't work if data in array === false):
while( ($row = next( $array)) !== false){
echo $row;
}
btw: I like hakre's answer most.
Using ArrayIterator
Probably studying documentation is the best comment for this one.
// Initialize array iterator
$obj = new ArrayIterator( $array);
$obj->seek(21); // Set to right position
while( $obj->valid()){ // Whether we do have valid offset right now
echo $obj->current() . "\n";
$obj->next(); // Switch to next object
}
$i = 0;
foreach ($query)
{
if ($i++ < 20) continue;
/* php code to execute if record 21+ */
}
if want to skipped some index then make an array with skipped index and check by in_array function inside the foreach loop if match then it will be skip.
Example:
//you have an array like that
$data = array(
'1' => 'Hello world',
'2' => 'Hello world2',
'3' => 'Hello world3',
'4' => 'Hello world4',
'5' => 'Hello world5',// you want to skip this
'6' => 'Hello world6',// you want to skip this
'7' => 'Hello world7',
'8' => 'Hello world8',
'9' => 'Hello world8',
'10' => 'Hello world8',//you want to skip this
);
//Ok Now wi make an array which contain the index wich have to skipped
$skipped = array('5', '6', '10');
foreach($data as $key => $value){
if(in_array($key, $skipped)){
continue;
}
//do your stuf
}
You have not told what "records" actually is, so as I don't know, I assume there is a RecordIterator available (if not, it is likely that there is some other fitting iterator available):
$recordsIterator = new RecordIterator($records);
$limited = new LimitIterator($recordsIterator, 20);
foreach($limited as $record)
{
...
}
The answer here is to use foreach with a LimitIterator.
See as well: How to start a foreach loop at a specific index in PHP
I'm not sure why you would be using a foreach for this goal, and without your code it's hard to say whether this is the best approach. But, assuming there is a good reason to use it, here's the smallest version I can think of off the top of my head:
$count = 0;
foreach( $someArray as $index => $value ){
if( $count++ < 20 ){
continue;
}
// rest of foreach loop goes here
}
The continue causes the foreach to skip back to the beginning and move on to the next element in the array. It's extremely useful for disregarding parts of an array which you don't want to be processed in a foreach loop.
for($i = 20; $i <= 68; $i++){
//do stuff
}
This is better than a foreach loop because it only loops over the elements you want.
Ask if you have any questions
array.forEach(function(element,index){
if(index >= 21){
//Do Something
}
});
Element would be the current value of index.
Index increases with each turn through the loop.
IE 0,1,2,3,4,5;
array[index];

change initial array inside the foreach loop?

i want to have a foreach loop where the initial array is changed inside the loop.
eg.
$array = array('red', 'blue');
foreach($array as $key => $value) {
$array[] = 'white';
echo $value . '<br />';
}
in this loop the loop will print out red and blue although i add another element inside the loop.
is there any way to change the initial array inside the loop so new elements will be added and the foreach will use the new array whatever is changed?
i need this kind of logic for a specific task:
i will have a if statement that search for a link. if that link exists, it is added to the array. the link content will be fetched to be examined if it contains another link. if so, this link is added, and the content will be fetched, so on so forth.. when no link is further founded, the foreach loop will exit
I don't think this is possible with a foreach loop, at least the way you wrote it : doesn't seem to just be the way foreach works ; quoting the manual page of foreach :
Note: Unless the array is referenced, foreach operates on a copy
of the specified array and not the
array itself.
Edit : after thinking a bit about that note, it is actually possible, and here's the solution :
The note says "Unless the array is referenced" ; which means this portion of code should work :
$i = 0;
$array = array('red', 'blue');
foreach($array as $key => & $value) {
$array[] = 'white';
echo $value . '<br />';
if ($i++ >= 5) {
break; // security measure to ensure non-endless loop
}
}
Note the & before $value.
And it actually displays :
red
blue
white
white
white
white
Which means adding that & is actually the solution you were looking for, to modify the array from inside the foreach loop ;-)
Edit : and here is the solution I proposed before thinking about that note :
You could do that using a while loop, doing a bit more work "by hand" ; for instance :
$i = 0;
$array = array('red', 'blue');
$value = reset($array);
while ($value) {
$array[] = 'white';
echo $value . '<br />';
if ($i++ >= 5) {
break; // security measure to ensure non-endless loop
}
$value = next($array);
}
Will get you this output :
red
blue
white
white
white
white
What you need to do is move the assignment inside the for loop and check the length of the array every iteration.
$array = array('red', 'blue');
for($i = 0; $i < count($array); $i++)
{
$value = $array[$i];
array_push($array, 'white');
echo $value . '<br />';
}
Be careful, this will cause an infinite loop (white will be added to the end of the array at every loop).
Maybe you should use some other way, like:
$ar = array('blue', 'red');
while ($a = array_pop($ar) {
array_push($ar, 'white');
}
Or something like this...
You can access the array by using the $key
$array = array('red', 'blue');
foreach($array as $key => $value) {
$array[$key] = 'white';
}
In order to be able to directly modify array elements within the loop
precede $value with &. In that case the value will be assigned by
reference. [source]
All you have to do to your old code is
precede $value with &
like so
$array = array('red', 'blue');
foreach($array as $key => &$value) {// <-- here
$array[] = 'white';
echo $value . '<br />';
}
A while loop would be a better solution.
while (list ($key, $value) = each ($array) ) {
$array[] = 'white';
echo $value . '<br />';
}
If you don't need the $key variable, as your example suggests then using $value = array_pop($array) instead if list ($key, $value) = each ($array) would be a less expensive option. see #enrico-carlesso's Answer Here
As your array is sequantial(numeric,indexed) and not associative then you could use a for loop instead.
for ($key = 0; $key < count($array); ++$key) {
$value = $array[$i];
$array[] = 'white';
echo $value . '<br />';
}
As a side note.
I don't understand why its &$value and not &array.
&$value would suggest you can only modify the current element within the loop.
&array would suggest you could modify all array elements within the loop, including adding/removing element.

Categories