PHP: Set value of nested array using variable as key - php

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.

Related

How to match and replace one array values to another array keys if they both start with the same letters?

I have two arrays:
$array_one = array('AA','BB','CC');
And:
$replacement_keys = array
(
""=>null,
"BFC"=>'john',
"ASD"=>'sara',
"CSD"=>'garry'
);
So far I've tried
array_combine and to make a loop and try to search for values but can't really find a solution to match the keys of the second array with the values of the first one and replace it.
My goal is to make a final output:
$new_array = array
(
''=>null,
'BB' => 'john',
'AA' => 'sara',
'CC' => 'garry'
);
In other words to find a matching first letter and than replace the key with the value of the first array.
Any and all help will be highly appreciated.
Here is a solution keeping both $replacement_keys and $array_one intact
$tempArray = array_map(function($value){return substr($value,0,1);}, $array_one);
//we will get an array with only the first characters
$new_array = [];
foreach($replacement_keys as $key => $replacement_key) {
$index = array_search(substr($key, 0, 1), $tempArray);
if ($index !== false) {
$new_array[$array_one[$index]] = $replacement_key;
} else {
$new_array[$key] = $replacement_key;
}
}
Here is a link https://3v4l.org/fuHSu
You can approach like this by using foreach with in_array
$a1 = array('AA','BB','CC');
$a2 = array(""=>null,"BFC"=>'john',"ASD"=>'sara',"CSD"=>'garry');
$r = [];
foreach($a2 as $k => $v){
$split = str_split($k)[0];
$split .= $split;
in_array($split, $a1) ? ($r[$split] = $v) : ($r[$k] = $v);
}
Working example :- https://3v4l.org/ffRWY

Sort array with additional array exceptions

I have for example two arrays:
One with exceptions:
array('dog', 'cat', 'macbook')
And another with all values:
array('computer', 'mom', 'cat', 'dog')
I would like to get sorted array with following order:
array('dog', 'cat', 'computer', 'mom') // first with exception order and another elements alphabetically
How to do it?
Here is my code
$exceptions = array('dog', 'cat', 'macbook');
$main_arr = array('computer', 'mom', 'cat', 'dog');
$temp = [];
$result_arr = [];
foreach($exceptions as $k => $v){
if(in_array($v, $main_arr)){
$result_arr[] = $v; // adding in result array which matches exceptions with main array
unset($main_arr[array_search($v,$main_arr)]); // unsetting from main array with matches with exception array
}
}
$main_arr = array_values(array_filter($main_arr)); // correcting indexing of main array
$result_arr = array_merge($result_arr, $main_arr);
print_r($result_arr);
You can write your custom code like this, anyway this code will work
combine the difference and intersection as this:
<?php
$seq = array('dog', 'cat', 'macbook');
$data = array('computer', 'mom', 'cat', 'dog');
array_merge(array_intersect($seq, $data), array_diff($data, $seq));
The following code does combine exceptions that are contained within values (in the same order as in $exceptions) with values, that have exceptions excluded.
$exceptions = ['dog', 'cat', 'macbook'];
$values = ['computer', 'mom', 'cat', 'dog'];
sort($values);
$values = array_merge(
array_intersect($exceptions, $values),
array_diff($values, $exceptions)
);
I would not bother with sort operating on all values, unless you have a larger list of exceptions. Then, the solution might be rewritten as:
$exceptSlice = array_intersect($exceptions, $values);
$valuesSlice = array_diff($values, $exceptSlice);
sort($valuesSlice);
$values = array_merge($exceptSlice, $valuesSlice);

Pushing an Array element into an existing multidimensional array in codeigniter

I have a query in codeigniter like this
$query_tutors = $this->db->get_where("tutor_info", array('tutor_id' => $tutor_id));
I have also other array elements that I want to pass in the query which depends on some conditions.
So how do I push other multidimensional array elements to the existing array so I can pass the variable as a whole in the query?
array_push is not working in this case.
$array = array();
$array = array("tutor_id" => $tutor_id);
$array = array("online" => $online); // want to merge this to the 1st array.
$query_tutors = $this->db->get_where("tutor_info", $array);
First you're doing it wrong.
$array = array();
$array = array("tutor_id" => $tutor_id);
You're recreating the array again, which will delete it from the memory. Either you have to use
$array['tutor_id'] = $tutor_id;
$array["online"] = $online;
or
$array = array('tutor_id' => $tutor_id, 'online' => $online);
or if you want to merge two arrays
$array = array_merge(array('tutor_id' => $tutor_id), array('tutor_id' => $tutor_id));
Your initial code
$array = [];
$array = ["tutor_id" => $tutor_id];
Now, if you want to add conditional merge, simply follow,
if($condition)
{
$array = array_merge($array, ["online" => $online]);
}
If $condition == true You final array will be,
$array = ['tutor_id' => $tutor_id, 'online' => $online];
You are almost there, just need to read a little bit more about associative arrays.
Solution:
$array = array();
$array["tutor_id"] = $tutor_id;
$array["online"] = $online;
$query_tutors = $this->db->get_where("tutor_info", $array);
This way your $array will have all indexes which you want.
You can do something like this:
$array = array();
if (!empty($tutor_id))
{
$array["tutor_id"] = $tutor_id;
}
if (!empty($online))
{
$array["online"] = $online;
}
$query_tutors = $this->db->get_where("tutor_info", $array);

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

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
?>

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.

Categories