PHP - Automatically creating a multi-dimensional array - php

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.

Related

Replace array value with more than one values

I have an array like this,
$array = array(
1,2,3,'4>12','13.1','13.2','14>30'
);
I want to find any value with an ">" and replace it with a range().
The result I want is,
array(
1,2,3,4,5,6,7,8,9,10,11,12, '13.1', '13.2', 14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30
);
My understanding:
if any element of $array has '>' in it,
$separate = explode(">", $that_element);
$range_array = range($separate[0], $separate[1]); //makes an array of 4 to 12.
Now somehow replace '4>12' of with $range_array and get a result like above example.
May be I can find which element has '>' in it using foreach() and rebuild $array again using array_push() and multi level foreach. Looking for a more elegant solution.
You can even do it in a one-liner like this:
$array = array(1,2,3,'4>12','13.1','13.2','14>30');
print_r(array_reduce(
$array,
function($a,$c){return array_merge($a,#range(...array_slice(explode(">","$c>$c"),0,2)));},
[]
));
I avoid any if clause by using range() on the array_slice() array I get from exploding "$c>$c" (this will always at least give me a two-element array).
You can find a little demo here: https://rextester.com/DXPTD44420
Edit:
OK, if the array can also contain non-numeric values the strategy needs to be modified: Now I will check for the existence of the separator sign > and will then either merge some cells created by a range() call or simply put the non-numeric element into an array and merge that with the original array:
$array = array(1,2,3,'4>12','13.1','64+2','14>30');
print_r(array_reduce(
$array,
function($a,$c){return array_merge($a,strpos($c,'>')>0?range(...explode(">",$c)):[$c]);},
[]
));
See the updated demo here: https://rextester.com/BWBYF59990
It's easy to create an empty array and fill it while loop a source
$array = array(
1,2,3,'4>12','13.1','13.2','14>30'
);
$res = [];
foreach($array as $x) {
$separate = explode(">", $x);
if(count($separate) !== 2) {
// No char '<' in the string or more than 1
$res[] = $x;
}
else {
$res = array_merge($res, range($separate[0], $separate[1]));
}
}
print_r($res);
range function will help you with this:
$array = array(
1,2,3,'4>12','13.1','13.2','14>30'
);
$newArray = [];
foreach ($array as $item) {
if (strpos($item, '>') !== false) {
$newArray = array_merge($newArray, range(...explode('>', $item)));
} else {
$newArray[] = $item;
}
}
print_r($newArray);

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

How to prevent duplicate keys from array_push

I have 2 2D arrays, how can i get the unique keys and only push those? For example:
$array = json_decode('[{"7654321":1368356071},{"1234567":1368356071}]',true);
$array2 = array(array(1234567 => time()), array(7654321 => time()), array(2345678 => time()));
//array_push($array, $array2[2]);
-- How can I dynamically get the unique key like $array2[2] in this example?
why not to use array_unique() function in php? http://php.net/manual/ru/function.array-unique.php
You mean, you would like to push into another array (let's say in $keys_unique) whatever key(s) that are present only in one of the first two arrays, but not present in both of them?
Try this:
$arrays_mixed = array( //your $array and $array2; you can put as many arrays as you want here
json_decode('[{"7654321":1368356071},{"1234567":1368356071}]',true)
,array(array(1234567 => time()), array(7654321 => time()), array(2345678 => time()))
);
//begin getting all keys
$arrays_keys = array(); //will hold all keys from arrays_mixed
$keys_unique = array(); //will hold all unique keys out of arrays_key
for($x=0;$x<count($arrays_mixed);$x++){
$arrays_keys[$x] = array(); //prepares a "keys holder"
$toflatten = $arrays_mixed[$x];
$c1 = 0;
do{
$arrmixed = array();
$arrclean = array();
foreach($toflatten as $a){
$arrmixed = $this->keys_finder($a,1);
$arrclean[$c1] = $this->keys_finder($a,2);
$c1++;
}
$toflatten = $arrmixed;
}while(is_array($toflatten));
for($c2=0;$c2<$c1;$c2++)
foreach($arrclean[$c2] as $ac)
array_push($arrays_keys[$x],$ac);
}//end geting all keys
//begin finding unique keys
foreach($arrays_keys as $ak)
foreach($ak as $add)
$keys_unique = $this->unique_inserter($arrays_keys,$keys_unique,$add);
//end finding unique keys
Here are the functions you need
function unique_inserter($arrays_keys,$keys_unique,$add){
$detector = 0; //detects how many arrays contain a value
foreach($arrays_keys as $ak)
if(in_array($add,$ak))
$detector++;
if($detector<2) //if value is found in one array only
array_push($keys_unique,$add);
return $keys_unique;
}
function keys_finder($array,$return){
$arrmixed = array();
$arrclean = array();
foreach($array as $key=>$a)
if(is_array($a))
foreach($a as $aa)
array_push($arrmixed,$aa);
else
array_push($arrclean,$key);
switch($return){
case 1:
return (count($arrmixed)==0)?'':$arrmixed;
break;
case 2:
return $arrclean;
break;
}
}
I have tested this code and it works on my side. Hope it helps.

How do I select last array per key in a multidimensional array

Given the following php array
$a = array(
array('a'=>'111','b'=>'two','c'=>'asdasd'),
array('a'=>'111','b'=>'one','c'=>'sdvsdfs'),
array('a'=>'111','b'=>'three','c'=>'vbndfgn'),
array('a'=>'222','b'=>'nine','c'=>'dfhfnd')
);
how can I return only the last array per array key 'a'?
Desired result:
$new = array(
array('a'=>'111','b'=>'three','c'=>'vbndfgn'),
array('a'=>'222','b'=>'nine','c'=>'dfhfnd')
);
If I were you, I'd try to store it in a better format that makes retrieving it a bit easier. However, if you are stuck with your format, then try:
$a = array(
array('a'=>'111','b'=>'two','c'=>'asdasd'),
array('a'=>'111','b'=>'one','c'=>'sdvsdfs'),
array('a'=>'111','b'=>'three','c'=>'vbndfgn'),
array('a'=>'222','b'=>'nine','c'=>'dfhfnd')
);
$tmp = array();
foreach ($a as $value) {
$tmp[$value['a']] = $value;
}
$new = array_values($tmp);
print_r($new);

How to edit an array's key?

Is it possible to edit the key once it has been made?
I know you can create an array with a different key but I couldn't see anything on the php site about editing the key latter.
Original array:
Array
(
[0] => first
[1] => color
)
What I would like:
Array
(
[newName] => first
[1] => color
)
If you want to change the key of an item, you must either set the value with the new key and unset() the old one (this technique changes the order of the array):
$arr['newName'] = $arr[0];
unset($arr[0]);
or use a wrapper that forgoes looping and allows you to modify the keys, as such:
function array_change_key(&$array, $search, $replace) {
$keys = array_keys($array);
$values = array_values($array);
// Return FALSE if replace key already exists
if(array_search($replace, $keys) !== FALSE) return FALSE;
// Return FALSE if search key doesn't exists
$searchKey = array_search($search, $keys);
if($searchKey === FALSE) return FALSE;
$keys[$searchKey] = $replace;
$array = array_combine($keys, $values);
return TRUE; // Swap complete
}
Here's an alternate, simple approach, which is probably fairly efficient, as long as you do all of your re-keying for each array in a single call:
<?php
function mapKeys(array $arr, array $map) {
//we'll build our new, rekeyed array here:
$newArray = array();
//iterate through the source array
foreach($arr as $oldKey => $value) {
//if the old key has been mapped to a new key, use the new one.
//Otherwise keep the old key
$newKey = isset($map[$key]) ? $map[$key] : $oldKey;
//add the value to the new array with the "new" key
$newArray[$newKey] = $value;
}
return $newArray;
}
$arr = array('first', 'color');
$map = array(0 => 'newName');
print_r(mapKeys($arr, $map));
$array = array('foo', 'bar');
$array['newName'] = $array[0];
unset($array[0]);
That's pretty much the only thing you can do.

Categories