PHP make a multidimensional associative array from key names - php

Even if it's documented, I need help to better understand this code (only references). I already checked tutorials, but they didn't help me.
// initialize variables
$val = 'it works !';
$arr = [];
// Get the keys we want to assign
$keys = [ 'key_1', 'key_2', 'key_3', 'key_4' ];
// Get a reference to where we start
$curr = &$arr;
// Loops over keys
foreach($keys as $key) {
// get the reference for this key
$curr = &$curr[$key];
}
// Assign the value to our last reference
$curr = $val;
// visualize the output, so we know its right
var_dump($arr);
echo "<hr><pre>\$arr : "; print_r($arr);
(Source : https://stackoverflow.com/a/31103901/4741362 #Derokorian)

I'll try to explain it for you to understand it a little better, see the working code here. I hope it helps you understand this $curr = &$curr[$key]; line. $curr points to the empty $arr before the foreach starts, In foreach it saves the value of $key into the $arr by reference which was pointed by $curr and then reassigns the reference of the newly saved $key in $arr to the $curr pointer again.
// initialize variables
$val = 'it works !';
$arr = [];
// Get the keys we want to assign
$keys = [ 'key_1', 'key_2', 'key_3', 'key_4' ];
// Get a reference to where we start
echo "create a space where to save the first key \r\n";
$curr = &$arr;
// Loops over keys
$i = 1;
foreach($keys as $key) {
echo "**************** Iteration no $i ******************\r\n";
// echo "save the value \"$key\" to the reference created earlier in the \$curr variable for the empty array above where the kesy are actually being saved \r\n";
// get the reference for this key
echo "Now save the value of \$key to the array reference present in \$curr and then assigne the reference of newly saved array item to \$curr again \r\n";
$curr = &$curr[$key];
print_r($arr);
$i++;
echo "\r\n\r\n";
}
// Assign the value to our last reference
$curr = $val;
// visualize the output, so we know its right
print_r($arr);

Related

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

Remove all elements in an array after the first instance of an element that matches same alphabetic (ONLY) value

I need to remove all elements in the array that comes after the FIRST instance of an element that matches same string value before the dot. ie, not taking into consideration any values after the .
from
$array = ("ItemNew1.1", "Item2.0", "Item3Test.0", "Item2.2", "Item4.4", "Item2.5")
to
$array = ("ItemNew1.1", "Item2.0", "Item3Test.0", "Item4.4")
The code below creates a temp array to hold the values that are already in the array, it runs a foreach on the original array and if the value is not in the temporary array, it inserts it into a new array
$tempArray = array();
$newArray = array();
foreach($array as $value) {
list($item, ) = explode(".", $value);
$int = filter_var($item, FILTER_SANITIZE_NUMBER_INT);
if(!in_array($int, $tempArray)) {
$newArray[] = $value;
$tempArray[] = $int;
}
}
Now, $newArray is the array that you want.
DEMO

PHP unreference

Lets say i have this code:
$val = 1;
$arr = Array();
$arr['val'] =& $val;
$val = 2;
echo $arr['val'];
This will print out 2, because $val was passed to $arr by reference.
My question is : if i passed a value to an array by reference, is there a way to remove that reference later on, making it a simple copied value ?
To make it clearer, i would like something like this:
$val = 1;
$arr = Array();
$arr['val'] =& $val;
$arr['val'] = clone $arr['val'];
// Or better yet:
$arr = clone $arr;
$val = 2;
echo $arr['val'];
And this should print out 1 (because the array was cloned, before the referenced variable changed).
Howerver, clone does not work with arrays, it only works with objects.
Any ideas? I really have no clue how to do this. I tried writing a recursive copy function, but that didn't work.
You could unset the index and then reassign by-value instead of by reference.
unset($arr['val']);
$arr['val'] = $val;

PHP - Automatically creating a multi-dimensional array

So here's the input:
$in['a--b--c--d'] = 'value';
And the desired output:
$out['a']['b']['c']['d'] = 'value';
Any ideas? I've tried the following code without any luck...
$in['a--b--c--d'] = 'value';
// $str = "a']['b']['c']['d";
$str = implode("']['", explode('--', key($in)));
${"out['$str']"} = 'value';
This seems like a prime candidate for recursion.
The basic approach goes something like:
create an array of keys
create an array for each key
when there are no more keys, return the value (instead of an array)
The recursion below does precisely this, during each call a new array is created, the first key in the list is assigned as the key for a new value. During the next step, if there are keys left, the procedure repeats, but when no keys are left, we simply return the value.
$keys = explode('--', key($in));
function arr_to_keys($keys, $val){
if(count($keys) == 0){
return $val;
}
return array($keys[0] => arr_to_keys(array_slice($keys,1), $val));
}
$out = arr_to_keys($keys, $in[key($in)]);
For your example the code above would evaluate as something equivalent to this (but will work for the general case of any number of -- separated items):
$out = array($keys[0] => array($keys[1] => array($keys[2] => array($keys[3] => 'value'))));
Or in more definitive terms it constructs the following:
$out = array('a' => array('b' => array('c' => array('d' => 'value'))));
Which allows you to access each sub-array through the indexes you wanted.
$temp = &$out = array();
$keys = explode('--', 'a--b--c--d');
foreach ($keys as $key) {
$temp[$key] = array();
$temp = &$temp[$key];
}
$temp = 'value';
echo $out['a']['b']['c']['d']; // this will print 'value'
In the code above I create an array for each key and use $temp to reference the last created array. When I run out of keys, I replace the last array with the actual value.
Note that $temp is a REFERENCE to the last created, most nested array.

How to get numeric key of new pushed item in PHP?

$arr[] = $new_item;
Is it possible to get the newly pushed item programmatically?
Note that it's not necessary count($arr)-1:
$arr[1]=2;
$arr[] = $new_item;
In the above case,it's 2
end() do the job , to return the value ,
if its help to you ,
you can use key() after to petch the key.
after i wrote the answer , i see function in this link :
http://www.php.net/manual/en/function.end.php
function endKey($array){
end($array);
return key($array);
}
max(array_keys($array)) should do the trick
The safest way of doing it is:
$newKey = array_push($array, $newItem) - 1;
You can try:
max(array_keys($array,$new_item))
array_keys($array,$new_item) will return all the keys associated with value $new_item, as an array.
Of all these keys we are interested in the one that got added last and will have the max value.
You could use a variable to keep track of the number of items in an array:
$i = 0;
$foo = array();
$foo[++$i] = "hello";
$foo[++$i] = "world";
echo "Elements in array: $i" . PHP_EOL;
echo var_dump($foo);
if it's newly created, you should probably keep a reference to the element. :)
You could use array_reverse, like this:
$arr[] = $new_item;
...
$temp = array_reverse($arr);
$new_item = $temp[0];
Or you could do this:
$arr[] = $new_item;
...
$new_item = array_pop($arr);
$arr[] = $new_item;
If you are using the array as a stack, which it seems like you are, you should avoid mixing in associative keys. This includes setting $arr[$n] where $n > count($arr). Stick to using array_* functions for manipulation, and if you must use indexes only do so if 0 < $n < count($arr). That way, indexes should stay ordered and sequential, and then you can rely on $arr[count($arr)-1] to be correct (if it's not, you have a logic error).

Categories