Dynamic add to current foreach array - php

I have a loop that needs to go through each item. So naturally a foreach loop seems like the best idea. However, I need to add an element to the array as it iterates. I tried the following without any luck.
foreach ($allitems as $item) {
//Do some stuff here
if ($value === true)
$allitems[] = 'New item';
}
I found out the foreach loops seem to use a referenced copy of the array, so editing the array does not register in the loop.
A workaround is to use the older styled while loops as follows:
while (list($key, $item) = each($allitems)) {
//Do some stuff here
if ($value === true)
$allitems[] = 'New item';
}
Clearly a foreach loop would be nicer and more efficient. Is it possible? Or is the while structure the best possible solution.

Yeah, it is possible:
foreach ($allitems as &$item) {
//Do some stuff here
if ($value === true)
$allitems[] = 'New item';
}
According to the docs, you need to pass a reference (using the & in front if $item)
More concrete example:
<?php
$allitems = array(1,2,3,4);
foreach ($allitems as &$item) {
echo $item."\n";
if ($item == 2) {
$allitems[] = "Blah";
}
}
?>
This outputs (using php from commandline)
1
2
3
4
Blah

It seems like an ordinary for loop would be best for this:
for ($i = 0; $i < count($array); $i++) {
// Do some stuff here that calculates $value from $array[$i]
if ($value === true) {
$array[] = "New Element";
}
}

You could do foreach...like this....
But it adds more code...so its not any better than your while loop..
foreach($array as $val){
if($val=="check"){$append[]="New Item";}
}
$array = array_merge($array, $append);
Of course, if you want your structure maintained..then rather use array_push

Related

Outputting odd and even number in array

Using below array, i'm trying to use foreach loop to iterate through each item. Then i need to apply if condition to check if the given number is even and odd. I also need to create two arrays one for even and one for odd and push each number in their respective category.
So i have done this so far:
These are the two arrays i created to push through the values to.
}
$numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13,14];
$array_odd = [];
$array_even = [];
foreach ($numbers as $value)
{
if (value %2 == 0)
{
$array_even = $value;
echo $array_even;
}
else
{
$array_odd = $value;
echo $array_odd;
}
I'd like to know if i'm using the correct solution or are there major errors im committing?
It will surely work like charms.
$numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13,14];
$array_odd = [];
$array_even = [];
foreach ($numbers as $value)
{
if ($value %2 == 0)
{
$array_even[] = $value;
}
else
{
$array_odd[] = $value;
}
}
echo "<pre>";
print_r($array_odd);
echo "<pre>";
print_r($array_even);

foreach leaves out the very first value

I am processing a foreach(first) which gives the full array in the data, when I make another foreach(second) and pass the first foreach into second foreach the first value of the first foreach never appears in the second foreach. Does anyone have any idea why the foreach behaves this way? is there a solution for this?
I tried it this way no luck
$userIdsPerRoom = chatRoomUsersId($_SESSION['currentRoomID']);
foreach ($userIdsPerRoom as $value) {
$list[] =$value['UserID'];
}
foreach ($list as $value) {
$userInfo = chatRoomUsersEmail($value);
foreach ($userInfo as $info) {
echo $info['userEmail'];
}
}
echo count($list); ///gives the full list
}
I noticed it with this code
$userIdsPerRoom = chatRoomUsersId($_SESSION['currentRoomID']); //return an array of intergers with five values example array(1,2,3,4,5)
foreach ($userIdsPerRoom as $value){
$userInfo = chatRoomUsersEmail($value['UserID']);
foreach ($userInfo as $info){
echo $info['userEmail']; /// I only get four values example array(b,c,d,e)
}
}

Search multidimensional arrays for specific keys and output their data

I have following array construction: $array[$certain_key][some_text_value]
And in a while loop, I want to print the data from the array, where $certain_key is a specific value.
I know how to loop through multidimensional arrays, which is not the complete solution to this problem:
foreach ($a as $v1) {
foreach ($v1 as $v2) {
echo "$v2\n";
}
}
I do not want to loop the whole array each time, but only when $certain_key is matched.
EDIT: to be more exact, this is what I'm trying to do:
$array[$array_key][some_text];
while reading from db {
//print array where a value returned from the db = $array_key
}
while ($row = fetch()) {
if (isset($array[$row['db_id']])) {
foreach ($array[$row['db_id']] as $some_text_value => $some_text_values_value) {
echo ...
}
}
}
foreach ($array as $certain_key => $value) {
if($certain_key == $row['db_id']) {
foreach ($value as $some_text_value) {
echo "$v2\n";
}
}
}
You mean like
foreach($array[$certain_key] as $k => $v)
{
do_stuff();
}
?
Maybe you're looking for array_key_exists? It works like this:
if(array_key_exists($certain_key, $array)) {
// do something
}
<?php
foreach ($a as $idx => $value) {
// replace [search_value] with whatever key you are looking for
if ('[search_value]' == $idx) {
// the key you are looking for is stored as $idx
// the row you are looking for is stored as $value
}
}

Anything to attend when changing values in a multidimensional foreach() loop?

I got a site that executes the following code
$keywords = ($_SESSION[$_POST['ts']]);
print_r($keywords);
foreach ($keywords as $keyword) {
foreach ($keyword['whitelist'] as $entry) {
foreach ($_POST as $key => $value) {
if ($key == $entry['encoded_url']) {
$entry['ignore'] = $value;
$decodedURL = $this->base64->url_decode($entry['encoded_url']);
if ($value == 'noignore') {
echo "found!<br />";
$this->blacklist_model->remove($decodedURL);
$html = $this->analyse->getHTML($decodedURL);
$entry['html'] = $html[0];
$entry['loading_time'] = $html[1];
}
if($value == 'alwaysignore') {
$this->blacklist_model->add($decodedURL);
}
}
}
}
}
print_r($keywords);
The output looks like this:
http://pastebin.com/B3PtrqjB
So, as you see, there are several "found!"s in the output, so the if clause actually gets executed a few times and I expected the second array to contain new data like 'html', but, as you see, nothing changes. Is there anything to attend when changing values in multidimensional foreach() loops?
foreach creates a copy of the array and loops through that. Modifying values doesn't work.
You can get around this, though, by using references.
foreach ($keywords as &$keyword) {
foreach ($keyword['whitelist'] as &$entry) {
foreach ($_POST as $key => &$value) {
...
}
}
}
With that you can modify $value and it WILL affect the original array.
You suppose to change the Original array.
$entry is just an instance / unconnected node.
you need to change $keywords, and not its on the fly created nodes.

in foreach, isLastItem() exists?

Using a regular for loop, it's possible to comapred the current index with the last to tell if I'm in the last iteration of the loop. Is there a similar thing when using foreach? I mean something like this.
foreach($array as $item){
//do stuff
//then check if we're in the last iteration of the loop
$last_iteration = islast(); //boolean true/false
}
If not, is there at least a way to know the current index of the current iteration like $iteration = 5, so I can manually compare it to the length of the $array?
The counter method is probably the easiest.
$i = count($array);
foreach($array as $item){
//do stuff
//then check if we're in the last iteration of the loop
$last_iteration = !(--$i); //boolean true/false
}
You can use a combination of SPL’s ArrayIterator and CachingIterator class to have a hasNext method:
$iter = new CachingIterator(new ArrayIterator($arr));
foreach ($iter as $value) {
$last_iteration = !$iter->hasNext();
}
Here are a few methods for this;
$items = ["Bhir", "Ekky", null, "Uych", "foo"=>"bar"];
$values = array_values($items);
// Bhir, Ekky, Uych, bar
foreach ($values as $i => $item) {
print("$item");
$next = isset($values[$i + 1]);
if ($next) {
print(", ");
}
}
// Bhir, Ekky, , Uych, bar
foreach ($values as $i => $item) {
print("$item");
$next = array_key_exists($i + 1, $values);
if ($next) {
print(", ");
}
}
// Bhir, Ekky, , Uych, bar
$i = count($values);
foreach ($items as $item) {
print("$item");
$next = !!(--$i);
if ($next) {
print(", ");
}
}
// Bhir, Ekky, , Uych, bar
$items = new \CachingIterator(new \ArrayIterator($items));
foreach ($items as $item) {
print("$item");
$next = $items->hasNext();
if ($next) {
print(", ");
}
}
No, you need to have a counter and know the amount of items in the list. You can use end() to get the last item in an array and see if it matches the current value in your foreach.
If you know that the values of the array will always be unique, you can compare the current $item to end($array) to know if you're at the last item yet. Otherwise, no, you need a counter.
You can get the key and the value in foreach() like this:
foreach($array as $key=>$value) { ... }
Alternatively, you could do a count() of the array so you know how many items there are and have an incrementing counter so that you know when you've reached the last item.
end($array);
$lastKey = key($array);
foreach($array as $key => $value) {
if ($key === $lastKey) {
// do something endish
}
}
The valid() method says if the ArrayIterator object has more elements.
See:
$arr = array("Banana","Abacaxi","Abacate","Morango");
$iter = new ArrayIterator($arr);
while($iter->valid()){
echo $iter->key()." - ".$iter->current()."<br/>";
$iter->next();
}

Categories