Can PHP's list() work with associative arrays? - php

Example:
list($fruit1, $fruit2) = array('apples', 'oranges');
code above of course works ok, but code below:
list($fruit1, $fruit2) = array('fruit1' => 'apples', 'fruit2' => 'oranges');
gives: Notice: Undefined offset: 1 in....
Is there any way to refer to named keys somehow with list like list('fruit1' : $fruit1), have you seen anything like this planned for future release?

With/from PHP 7.1:
For keyed arrays;
$array = ['fruit1' => 'apple', 'fruit2' => 'orange'];
// [] style
['fruit1' => $fruit1, 'fruit2' => $fruit2] = $array;
// list() style
list('fruit1' => $fruit1, 'fruit2' => $fruit2) = $array;
echo $fruit1; // apple
For unkeyed arrays;
$array = ['apple', 'orange'];
// [] style
[$fruit1, $fruit2] = $array;
// list() style
list($fruit1, $fruit2) = $array;
echo $fruit1; // apple
Note: use [] style if possible by version, maybe list goes a new type in the future, who knows...

EDIT: This approach was useful back in the day (it was asked & answered nine years ago), but see Kerem's answer below for a better approach with newer PHP 7+ syntax.
Try the extract() function. It will create variables of all your keys, assigned to their associated values:
extract(array('fruit1' => 'apples', 'fruit2' => 'oranges'));
var_dump($fruit1);
var_dump($fruit2);

What about using array_values()?
<?php
list($fruit1, $fruit2) = array_values( array('fruit1'=>'apples','fruit2'=>'oranges') );
?>

It's pretty straightforward to implement.
function orderedValuesArray(array &$associativeArray, array $keys, $missingKeyDefault = null)
{
$result = [];
foreach ($keys as &$key) {
if (!array_key_exists($key, $associativeArray)) {
$result[] = $missingKeyDefault;
} else {
$result[] = $associativeArray[$key];
}
}
return $result;
}
$arr = [
'a' => 1,
'b' => 2,
'c' => 3
];
list($a, $b, $c) = orderedValuesArray($arr, ['a','AAA', 'c', 'b']);
echo $a, ', ', $b, ', ', $c, PHP_EOL;
output: 1, , 3
less typing on usage side
no elements order dependency (unlike array_values)
direct control over variables names (unlike extract) - smaller name collision risk, better IDE support

If you are in my case:
list() only works on numerical array. So if you can, leaving blank in fetch() or fetchAll() -> let it have 2 options: numerical array and associative array. It will work.

consider this an elegant solution:
<?php
$fruits = array('fruit1'=> 'apples','fruit2'=>'oranges');
foreach ($fruits as $key => $value)
{
$$key = $value;
}
echo $fruit1; //=apples
?>

<?php
function array_list($array)
{
foreach($array as $key => $value)
$GLOBALS[$key] = $value;
}
$array = array('fruit2'=>'apples','fruit1'=>'oranges');
array_list($array);
echo $fruit1; // oranges
?>

Related

How to keep only empty elements in array in php?

I have one array and i want to keep only blank values in array in php so how can i achieve that ?
My array is like
$array = array(0=>5,1=>6,2=>7,3=>'',4=>'');
so in result array
$array = array(3=>'',4=>'');
I want like this with existing keys.
You can use array_filter.
function isBlank($arrayValue): bool
{
return '' === $arrayValue;
}
$array = array(0 => 5, 1 => 6, 2 => 7, 3 => '', 4 => '');
var_dump(array_filter($array, 'isBlank'));
use for each loop like this
foreach($array as $x=>$value)
if($value=="")
{
$save=array($x=>$value)
}
if you want print then use print_r in loop
there is likely a fancy built in function but I would:
foreach($arry as $k=>$v){
if($v != ''){
unset($arry[$k]);
}
}
the problem is; you are not using an associative array so I am pretty sure the resulting values would be (from your example) $array = array(0=>'',1=>''); so you would need to:
$newArry = array();
foreach($arry as $k=>$v){
if($v == ''){
$newArry[$k] = $v;
}
}

PHP: Set value of nested array using variable as key

Lets say i have this kind of code:
$array = [
'a'=> [
'b' => [
'c'=>'some value',
],
],
];
$array['a']['b']['c'] = 'new value';
Of course this is working, but what i want is to update this 'c' key using variable, something like that:
$keys = '[a][b][c]';
$array{$keys} = 'new value';
But keys are treatening as string and this is what i get:
$array['[a][b][c]'] = 'new value';
So i would like some help, to show me the right way to make this work without using eval().
By the way, there can be any number of array nests, so something like this is not a good answer:
$key1 = 'a';
$key2 = 'b';
$key3 = 'c';
$array[$key1][$key2][$key3] = 'new value';
It isn't the best way to define your keys, but:
$array = [];
$keys = '[a][b][c]';
$value = 'HELLO WORLD';
$keys = explode('][', trim($keys, '[]'));
$reference = &$array;
foreach ($keys as $key) {
if (!array_key_exists($key, $reference)) {
$reference[$key] = [];
}
$reference = &$reference[$key];
}
$reference = $value;
unset($reference);
var_dump($array);
If you have to define a sequence of keys in a string like this, then it's simpler just to use a simple separator that can be exploded rather than needing to trim as well to build an array of individual keys, so something simpler like a.b.c would be easier to work with than [a][b][c]
Demo
Easiest way to do this would be using set method from this library:
Arr::set($array, 'a.b.c', 'new_value');
alternatively if you have keys as array you can use this form:
Arr::set($array, ['a', 'b', 'c'], 'new_value');
Hi bro you can do it like this throught an array of keys :
This is your array structured :
$array = array(
'a'=> array(
'b' => array(
'c'=>'some value',
),
),
);
This is the PHP code to get value from your array with dynamic keys :
$result = $array; //Init an result array by the content of $array
$keys = array('a','b','c'); //Make an array of keys
//For loop to get result by keys
for($i=0;$i<count($keys);$i++){
$result = $result[$keys[$i]];
}
echo $result; // $result = 'new value'
I hope that the answer help you, Find here the PHPFiddle of your working code.

Is there a way to loop through a multidimensional array without knowing it's depth?

So far, if I have to loop through a multidimensional array, I use a foreach loop for each dimension.
e.g for two dimensions
foreach($array as $key=>$value)
{
foreach($value as $k2=>$v2)
{
echo
}
}
What do I do when I don't know the depth of the array? ie the depth is variable.
The only thing I can think of is to code a whole stack of loops and to break the loop if the next value is not an array.This seems a little silly.
Is there a better way?
Yes, you can use recursion. Here's an example where you output all the elements in an array:
function printAll($a) {
if (!is_array($a)) {
echo $a, ' ';
return;
}
foreach($a as $v) {
printAll($v);
}
}
$array = array('hello',
array('world',
'!',
array('whats'),
'up'),
array('?'));
printAll($array);
What you should always remember when doing recursion is that you need a base case where you won't go any deeper.
I like to check for the base case before continuing the function. That's a common idiom, but is not strictly necessary. You can just as well check in the foreach loop if you should output or do a recursive call, but I often find the code to be harder to maintain that way.
The "distance" between your current input and the base case is called a variant and is an integer. The variant should be strictly decreasing in every recursive call. The variant in the previous example is the depth of $a. If you don't think about the variant you risk ending up with infinite recursions and eventually the script will die due to a stack overflow. It's not uncommon to document exactly what the variant is in a comment before recursive functions.
You can do the below function for loop-through-a-multidimensional-array-without-knowing-its-depth
// recursive function loop through the dimensional array
function loop($array){
//loop each row of array
foreach($array as $key => $value)
{
//if the value is array, it will do the recursive
if(is_array($value) ) $array[$key] = loop($array[$key]);
if(!is_array($value))
{
// you can do your algorithm here
// example:
$array[$key] = (string) $value; // cast value to string data type
}
}
return $array;
}
by using above function, it will go through each of the multi dimensional array, below is the sample array you could pass to loop function :
//array sample to pass to loop() function
$data = [
'invoice' => [
'bill_information' => [
'price' => 200.00,
'quantity' => 5
],
'price_per_quantity' => 50.00
],
'user_id' => 20
];
// then you can pass it like this :
$result = loop($data);
var_dump($result);
//it will convert all the value to string for this example purpose
You can use recursion for this problem:
Here is one example
$array = array(1 => array(1 => "a", 2 => array(1 => "b", 2 => "c", 3 => array(1 => "final value"))));
//print_r($array);
printAllValues($array);
function printAllValues($arr) {
if(!is_array($arr)) {
echo '<br />' . $arr;
return;
}
foreach($arr as $k => $v) {
printAllValues($v);
}
}
It will use recursion to loop through array
It will print like
a
b
c
final value
Simple function inside array_walk_recursive to show the level of nesting and the keys and values:
array_walk_recursive($array, function($v, $k) {
static $l = 0;
echo "Level " . $l++ . ": $k => $v\n";
});
Another one showing use with a reference to get a result:
array_walk_recursive($array, function($v) use(&$result) {
$result[] = $v;
});
Based on previous recursion examples, here is a function that keeps an array of the path of keys a value is under, in case you need to know how you got there:
function recurse($a,$keys=array())
{
if (!is_array($a))
{
echo implode("-", $keys)." => $a <br>";
return;
}
foreach($a as $k=>$v)
{
$newkeys = array_merge($keys,array($k));
recurse($v,$newkeys);
}
}
recurse($array);

Notice: Undefined index when trying to increment an associative array in PHP

I'm trying to increment the value for $variable each time a duplicate variable occurs. I'm not sure if this is syntactically correct, but I think this is semantically correct. var_dump seems to spit out the correct outputs, but i get this error: Notice: Undefined index...
$newarray = array();
foreach ($array as $variable)
{
$newarray[$variable]++;
var_dump($newarray);
}
$array = (0 => h, 1 => e, 2 => l, 3=> l, 4=> o);
goal:
'h' => int 1
'e' => int 1
'l' => int 2
'o' => int 1
My code works, it's just that I get some weird NOTICE.
$newarray = array();
foreach ($array as $variable)
{
if (!isset($newarray[$variable])) {
$newarray[$variable] = 0;
}
$newarray[$variable]++;
}
Take a look at the function array_count_values(). It does exactly what you are trying to do.
Sample from php.net:
$array = array(1, "hello", 1, "world", "hello");
print_r(array_count_values($array));
Result:
Array
(
[1] => 2
[hello] => 2
[world] => 1
)
In modern PHP, you can avoid the isset() call by leveraging the null coalescing operator. In the snippet below, the technique sets the variable to 0 if the variable is not yet declared. Then you can freely use a range of shorthand manipulations such as concatenation, arithmetic, etc.
$new = [];
foreach ($array as $v) {
$new[$v] = ($new[$v] ?? 0) + 1;
}
Or if you want to continue using ++, then you can use the "null coalescing assignment operator". The logic on the right side of assignment is not even executed if the variable is already declared. The below snippet will perform identically to the above snippet.
$new = [];
foreach ($array as $v) {
$new[$v] ??= 0;
++$new[$v];
}
<?php
$newarray = array();
foreach ($array as $variable) {
if ( !array_key_exists($variable, $newarray) ) {
$newarray[$variable] = 0;
}
++$newarray[$variable];
}
var_dump($newarray);
But you could also use array_count_values() instead.
$newarray = array();
foreach ($array as $variable)
{
if(!isset($newarray[$variable]))
$newarray[$variable] = 0;
$newarray[$variable]++;
var_dump($newarray);
}
You are incrementing the wrong thing, try this instead:
foreach ($array as $key => $variable) {
$array[$key]++;
var_dump($array);
}

in php how do i make an like array("one","two","three") into $somearray["one"]["two"]["three"]?

I would like to take an array, say:
array("one", "two", "three");
and make it into an array of arrays, like:
$someArray["one"]["two"]["three"];
The array of arrays ($someArray) would have to be created by some sort of loop as the initial array is created by an explode() so i don't know how deep $someArray would be.
I hope this is clear, thanks all for your time!
I am reading up on it at the moment myself, would array_map() work for this?
You can do this:
$path = array("one", "two", "three");
$ref = &$arr;
foreach ($path as $key) {
if (!isset($ref[$key])) break;
$ref = &$ref[$key];
}
At the end $ref is a reference to $arr['one']['two']['three'] if it exists. And if you replace break by $ref[$key] = array() you will build an array with that structure instead.
You should use array_reduce.
The solution is quite simple.
To do the trick, reverse the array and only then apply the reduction.
$a = array('a','b','c');
$x = array_reduce(array_reverse($a), function ($r, $c) {
return array($c=>$r);
},array());
EDIT an expanded and explained version:
In php we don't have a function to go deep into an array automatically but we haven't to.
If you start from the bottom, we will be able to enclose an array into the previous one
with a simple assignation.
$a = array('a','b','c');
$result=array(); // initially the accumulator is empty
$result = array_reduce(
array_reverse($a),
function ($partialResult, $currentElement) {
/* enclose the partially computed result into a key of a new array */
$partialResult = array($currentElement=>$partialResult);
return $partialResult;
},
$result
);
By the way I prefer the shorter form. I think it is a functional idiom and doesn't need further explanation to a middle experienced developer (with a bit of functional background). The second one add a lot of noise that, it is suitable to learn but source
of distraction into production code (obviously I'm referring to function with just a return statement).
i'm not sure why you would want this.
But but the basis of what your wanting would be like this
$numbers = array("one", "two", "three");
$array = array();
$pointer = &$array;
$last_val = NULL;
foreach($numbers as $key => $val){
if(!empty($pointer[$last_val])){
$pointer = &$pointer[$last_val];
$pointer = new array($val);
$last_val = $val;
}else{
$pointer = new array($val);
$last_val = $val;
}
}
This should then right what you want to $array;
This is untested but i think that should work if it does not just tell me what its doing and i will have a look
$arrNew = array();
$ref = &$arrNew;
$arrParts = array("one", "two", "three");
foreach($arrParts as $arrPart){
$ref[$arrPart] = array();
$ref = &$ref[$arrPart];
}
When you print $arrNew, It will print this..
Array
(
[one] => Array
(
[two] => Array
(
[three] => Array
(
)
)
)
)

Categories