I need to get every key-value-pair from an array in PHP. The structure is different and not plannable, for example it is possible that a key contains an additional array and so on (multidimensional array?). The function I would like to call has the task to replace a specific string from the value. The problem is that the function foreach, each, ... only use the main keys and values.
Is there existing a function that has the foreach-function with every key/value?
There is not a built in function that works as you expect but you can adapt it using the RecursiveIteratorIterator, walking recursively the multidimensional array, and with the flag RecursiveIteratorIterator::SELF_FIRST, you would get all the elements of the same level first, before going deeper, not missing any pair.
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($array), RecursiveIteratorIterator::SELF_FIRST);
foreach ($iterator as $key => $item) {
// LOGIC
}
The usual approach to this kind of task is using a recursive funcion.
Let's go step by step:
First you need the foreach control statement...
http://php.net/manual/en/control-structures.foreach.php
..that let you parse the associative array without knowing keys' names beforehand.
Then is_array and is_string (and eventually is_object, is_integer...) let you check the type of each value so you can act properly.
http://php.net/manual/en/function.is-array.php
http://php.net/manual/en/function.is-string.php
If you find the string to be operated then you do the replace task
If you find an array the function recalls itself passing the array just parsed.
This way the original array will be parsed down to the deepest level without missing and key-value pair.
Example:
function findAndReplaceStringInArray( $theArray )
{
foreach ( $theArray as $key => $value)
{
if( is_string( $theArray[ $key ] )
{
// the value is a string
// do your job...
// Example:
// Replace 'John' with 'Mike' if the `key` is 'name'
if( $key == 'name' && $theArray[ $key ] == "John" )
{
$theArray[ $key ] = "Mike";
}
}
else if( is_array( $theArray[ $key ] )
{
// treat the value as a nested array
$nestedArray = $theArray[ $key ];
findAndReplaceStringInArray( $nestedArray );
}
}
}
You can create a recursive function to treat it.
function sweep_array(array $array)
{
foreach($array as $key => $value){
if(is_array($value))
{
sweep_array($value);
}
else
{
echo $key . " => " . $value . "<br>";
}
}
}
Related
I want to update an array inside foreach I tried this two code :
code 1 :
foreach ($listOrders as $k => $order) {
foreach ($listOrders as $key => $o)
{
if ($o["id_order"] == $order["id_order"])
{
unset($listOrders[$key]);
}
}
in this codeunset is not working
code 2 :
foreach ($listOrders as $k => &$order) {
foreach ($listOrders as $key => $o)
{
if ($o["id_order"] == $order["id_order"])
{
unset($listOrders[$key]);
}
}
If I use & with $order $listOrders will not returned all data that I want.
Your error should be here
foreach ($listOrders as $k => &$order) {
^
Remove &
Also you are iterating through your $listOrders twice with your code, won't your array list always be empty after the iteration is finished?
If you are simply trying to get a list of the orders in the list, you can use array_column() to index the list by id_order. As you can only ever have 1 entry in an array with a particular key, this will end up with the last entry with a particular order id in the array...
$uniqueList = array_column(listOrders, null, "id_order");
If you just need the list without the index, you can use array_values() to re-index the list.
$uniqueList = array_values(array_column(listOrders, null, "id_order"));
I'm trying to foreach through an array of objects inside an array. I'm not receiving errors, but it seems not to be storing the new value I'm trying to establish. I've found many answers on here closely related to this question, but I'm not understanding, and I'm hoping someone can make this clearer.
Essentially, this converts kg to lbs.
$kg_conv = 2.20462262;
$weights = array($data['progress']->weight, $data['progress']->squats,
$data['progress']->bench, $data['progress']->deadlift);
foreach ($weights as $value) {
$value = $value * $kg_conv;
}
The values in the array come out unchanged. From what I've read, I should be using $data['progress'] and iterating through that, but I'm not understanding how to refer to only some of the elements inside instead of all of them. I also tried cutting out some redundancy by storing the objects in $progress instead of $data['progress'] but still not success.
UPDATE: The following has not worked
1
foreach ($weights as &$value) {
$value = $value * $kg_conv;
}
2
foreach ($weights as $key => &$value) {
$value = $value * $kg_conv;
}
3
foreach ($weights as $key => $value) {
$weights[$key] = $value * $kg_conv;
}
it does not work because you do not modify data array, you only modify copy made from this array, which is another array in memory
Solution: (will work for object's fields too)
$kg_conv = 2.20462262;
$weights = ['weight', 'squats','bench', 'deadlift'];
foreach ($data['progress'] as $key=>&$value) {
if ( in_array($key,$weights)
$value = $value * $kg_conv;
}
$value contains only a copy of the array element.
You can pass the object by reference like this:
foreach ($weights as &$value) {
$value = $value * $kg_conv;
}
Note the & before $value.
See References Explained in the php documentation or What's the difference between passing by reference vs. passing by value? here on stackoverflow.
Edit 2:
But note that this will only change the values in the $weights array, not your object stored in $data['progress'], as it's value has been copied into $weights. To achieve this, you can reference the object properties when constructing the data array in the following way (this step was commented out in my testcase code) :
$weights = array(&$data['progress']->weight, &$data['progress']->squats,
&$data['progress']->bench, &$data['progress']->deadlift);
Note the & operator again.
But probably the solution of maxpower is cleaner for your requirement.
Edit:
After your comment I created the following test case which works fine:
<?php
class foo {
public $test = 5;
public $test2 = 10;
}
$obj = new foo();
$obj2 = new foo();
$obj2->test = 3;
$data = array('progress' => $obj, 'p2' => $obj2);
// this copies the values into the new array
$weights = array($data['progress']->test, $data['progress']->test2);
// this makes a reference to the values, the original object will be modified
// $weights = array(&$data['progress']->test, &$data['progress']->test2);
var_dump($weights);
$kg_conv = 2.20462262;
foreach ($weights as &$value) {
$value = $value * $kg_conv;
}
var_dump($weights);
The result is:
array(2) {
[0]=>
int(5)
[1]=>
int(10)
}
array(2) {
[0]=>
float(11.0231131)
[1]=>
&float(22.0462262)
}
The PHP foreach manual describes this topic in great detail. To summarise why you are not seeing the results you expect, here is a short explanation.
Imagine you have an array $arr = ['one', 'two', 'three']. When you execute a foreach loop on this array, PHP will internally create a copy of your array:
foreach ($arr as $key => $value) {
$value = 'something'; // You are modifying the copy, not the original!
}
To modify the original array, you have two options.
Use the $key variable to access the element at given key in the original array:
$arr[$key] = 'something'; // Will change the original array
Tell PHP to use a reference to the original element in $value:
foreach ($arr as $key => &$value) {
$value = 'something'; // $value is reference, it WILL change items in $arr
}
Both approaches are valid; however, the second is more memory-efficient because PHP does not have to copy your array when you loop through it - it simply references the original.
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. In your example code should look like this:
foreach ($weights as &$value) {
$value = $value * $kg_conv;
}
But referencing $value is only possible if the iterated array can be referenced (i.e. if it is a variable).
You can also use indexes to acces array value directly. This code works pretty fine too:
foreach ($weights as $key => $value) {
$weights[$key] = $value * $kg_conv;
}
More here: http://php.net/manual/en/control-structures.foreach.php
I'm trying to modify an array when looping through it and increment certain values.
$data = ['traits' => [[['amt' => 1]]]];
var_dump($data['traits']);
foreach ($data['traits'] as $key => &$index) {
foreach ($index as $key => &$value) {
$value['amt'] = $value['amt']++; // This should increment
if (in_array($key, $input)) {
$i++;
$insert["field_".$i] = $key."_1";
}
}
}
var_dump($data['traits']); // SAME AS PREVIOUS VAR_DUMP
What you are doing in the loop is undefined:
$value['amt'] = $value['amt']++;
The outcome of that depends on what's evaluated first. In this case $value['amt']++ seems to be evaluated first and then assigned to $value['amt'] again; the side effect of the increment is lost.
On the other hand, the following statement will work as expected:
$value['amt']++;
Im trying to add a key=>value to a existing array with a specific value.
Im basically looping through a associative array and i want to add a key=>value foreach array that has a specific id:
ex:
[0] => Array
(
[id] => 1
[blah] => value2
)
[1] => Array
(
[id] => 1
[blah] => value2
)
I want to do it so that while
foreach ($array as $arr) {
while $arr['id']==$some_id {
$array['new_key'] .=$some value
then do a array_push
}
}
so $some_value is going to be associated with the specific id.
The while loop doesn't make sense since keys are unique in an associative array. Also, are you sure you want to modify the array while you are looping through it? That may cause problems. Try this:
$tmp = new array();
foreach ($array as $arr) {
if($array['id']==$some_id) {
$tmp['new_key'] = $some_value;
}
}
array_merge($array,$tmp);
A more efficient way is this:
if(in_array($some_id,$array){
$array['new_key'] = $some_value;
}
or if its a key in the array you want to match and not the value...
if(array_key_exists($some_id,$array){
$array['new_key'] = $some_value;
}
When you use:
foreach($array as $arr){
...
}
... the $arr variable is a local copy that is only scoped to that foreach. Anything you add to it will not affect the $array variable. However, if you call $arr by reference:
foreach($array as &$arr){ // notice the &
...
}
... now if you add a new key to that array it will affect the $array through which you are looping.
I hope I understood your question correctly.
If i understood you correctly, this will be the solution:
foreach ($array as $arr) {
if ($arr['id'] == $some_id) {
$arr[] = $some value;
// or: $arr['key'] but when 'key' already exists it will be overwritten
}
}
I have a multidimensional array, I am interested in getting all the elements (one level deep) that don't have named keys.
i.e.
Array
{
['settings'] {...}
['something'] {...}
[0] {...} // I want this one
['something_else'] {...}
[1] {...} // And this one
}
Any ideas? Thanks for your help.
This is one way
foreach (array_keys($array) as $key) {
if(is_int($key)) {
//do something
}
}
EDIT
Depending on the size of your array it may be faster and more memory efficient to do this instead. It does however require that the keys are in order and none are missing.
for($i=0;isset($array[$i]);$i++){
//do something
}
$result = array();
foreach ($initial_array as $key => $value)
if ( ! is_string( $key ) )
$result[ $key ] = $value;
The key is 0, Shouldn't be $your_array[0]?