string to associative array conversion - php

I've been struggling with this for a few days and wanted to throw it out there and see if someone has any ideas.
Basically I have a string e.g
1) "/0/bar"
2) "/build/0/foo/1"
and need to convert this into a multidimensional array
1) $result[0][bar]
2) $result[build][0][foo][1]
So far I've tried:
$query = "/build/0/foo/1";
$queryAr = [];
$current = &$queryAr;
$keys = explode("/", $query);
foreach($keys as $key) {
#$current = &$current[$key];
}
$current = $value;
quieting the output is a pretty hacky way to achive this...

You need to trim the first / of the string. live demo.
<?php
$query = "/build/0/foo/1";
$queryAr = [];
$current = &$queryAr;
$keys = explode("/", trim($query, '/'));
foreach($keys as $key) {
#$current = &$current[$key];
}
$current = $value;
print_r($queryAr);

I tried a recursive function version:
$query = "/build/0/foo/1";
print_r($result = buildNestedArray(explode('/', trim($query, '/'))));
function buildNestedArray($keys)
{
$k = current($keys);
$result = [$k => 'DONE'];
array_shift($keys);
if (sizeof($keys) > 0) { $result[$k] = buildNestedArray($keys); }
return $result;
}
output: Array ( [build] => Array ( [0] => Array ( [foo] => Array ( [1] => DONE ) ) ) )

Related

Split an array by key

I have an array with the following keys:
Array
{
[vegetable_image] =>
[vegetable_name] =>
[vegetable_description] =>
[fruit_image] =>
[fruit_name] =>
[fruit_description] =>
}
and I would like to split them based on the prefix (vegetable_ and fruit_), is this possible?
Currently, I'm trying out array_chunk() but how do you store them into 2 separate arrays?
[vegetables] => Array { [vegetable_image] ... }
[fruits] => Array { [fruit_image] ... }
This should work for you:
$fruits = array();
$vegetables = array();
foreach($array as $k => $v) {
if(strpos($k,'fruit_') !== false)
$fruits[$k] = $v;
elseif(strpos($k,'vegetable_') !== false)
$vegetables[$k] = $v;
}
As an example see: http://ideone.com/uNi54B
Out of the Box
function splittArray($base_array, $to_split, $delimiter='_') {
$out = array();
foreach($to_split as $key) {
$search = $key.delimiter;
foreach($base_array as $ok=>$val) {
if(strpos($ok,$search)!==false) {
$out[$key][$ok] = $val;
}
}
return $out;
}
$new_array = splittArray($array,array('fruit','vegetable'));
It is possible with array_reduce()
$array = ['foo_bar' => 1, 'foo_baz' => 2, 'bar_fee' => 6, 'bar_feo' => 9, 'baz_bee' => 7];
$delimiter = '_';
$result = array_reduce(array_keys($array), function ($current, $key) use ($delimiter) {
$splitKey = explode($delimiter, $key);
$current[$splitKey[0]][] = $key;
return $current;
}, []);
Check the fiddle
Only one thins remains: you are using different forms (like "vegetable_*" -> "vegetables"). PHP is not smart enough to substitute language (that would be English language in this case) transformations like that. But if you like, you may create array of valid forms for that.
Use explode()
$arrVeg = array();
$arrFruit = array();
$finalArr = array();
foreach($array as $k => $v){
$explK = explode('_',$k);
if($explK[0] == 'vegetable'){
$arrVeg[$k] = $v;
} elseif($explK[0] == 'fruit') {
$arrFruit[$k] = $v;
}
}
$finalArr['vegetables'] = $arrVeg;
$finalArr['fruits'] = $arrFruit;
Use simple PHP array traversing and substr() function.
<?php
$arr = array();
$arr['vegetable_image'] = 'vegetable_image';
$arr['vegetable_name'] = 'vegetable_name';
$arr['vegetable_description'] = 'vegetable_description';
$arr['fruit_image'] = 'fruit_image';
$arr['fruit_name'] = 'fruit_name';
$arr['fruit_description'] = 'fruit_description';
$fruits = array();
$vegetables = array();
foreach ($arr as $k => $v) {
if (substr($k, 0, 10) == 'vegetable_') {
$vagetables[$k] = $v;
}
else if (substr($k, 0, 6) == 'fruit_') {
$fruits[$k] = $v;
}
}
print_r($fruits);
print_r($vagetables);
Working Example

Accessing the nth element in multidimensional array

is there a simple way to access the nth element in a multidimensional array in php?
so for example
$arr = array(
[0] => array(1,4,7,3,53),
[6] => array(6,3,9,12,51,7),
[2] => array(9,94,54,3,87));
the 12th element would be 9.
array keys are not necessarily in order, nor each array row is of the same length.
Try this :
<?php
$arr = array(
'0'=> array(1,4,7,3,53),
'6'=>array(6,3,9,12,51,7),
'2'=>array(9,94,54,3,87)
);
$newArray=array();
foreach($arr as $array){
$newArray=array_merge($newArray, $array);
}
echo $newArray[11];
?>
untested, should work...
$arr = array(
0 => array(1,4,7,3,53), // your code was wrong here
6 => array(6,3,9,12,51,7),
2 => array(9,94,54,3,87));
function getnth ($array, $offset) {
$tmp_arr = array();
foreach ($array as $key => $value) {
foreach ($value as $val) {
$tmp_arr[] = $val;
}
}
return (isset($tmp_arr[$offset -1]) ? $tmp_arr[$offset -1] : FALSE);
}
getnth($arr, 12);
Edit: got to admit, the array_merge version is better....
Edit2: this is probably faster, if performance is an issue....
function getnth($array, $offset) {
$i = 0;
foreach ($array as $key => $value){
$size = count($value);
$i += $size;
if($offset <= $i) {
$new_off = $size - ($i - $offset) -1 ;
return $value[$new_off];
}
}
return FALSE;
}
function get_item($arr, $path, $delim = '.') {
$path = explode($delim, $path);
$result = $arr;
foreach ($path as $item) {
if (isset($result[$item])) {
$result = $result[$item];
} else {
return null;
}
}
return $result;
}
using:
echo get_item($arr, 'item.value.3.4.2.etc');

PHP Convert Array To An Associative Array

How do I convert the array
Array
(
[1] => a,b,c
[2] => x,y,z
)
into an associative array like
Array
(
[a]=> b,c
[x]=> y,z
)
Basically want to convert value of an array into a key.
How about this:
$arr = array('a,b,c','x,y,z');
$newArr = array();
foreach($arr as $key => $value) {
$value = explode(",",$value);
$firstValue = $value[0];
array_shift($value);
$newArr[$firstValue] = implode(",",$value);
}
print_r($newArr); //Array ( [a] => b,c [x] => y,z )
A faster solution:
foreach($array as $item){
$x = explode(',',$item);
$new_array[$x[0]] = implode(','array($x[1],$x[2]));
}
print_r($new_array);
Try out this,
$newArray = array();
foreach($array as $data){
$values = explode(",",$data);
$key = array_shift($values);
$newArray[$key] = implode($values,",");
}
print_r($newArray);
DEMO.
Do this:
$myArray=array(1=>'a,b,c', 2=>x,y,z);
foreach($myArray as $val){
$Xval=explode(",",$val);
$newKey=$Xval[0];
unset($Xval[0]);
$newArray[$newKey]=implode(",",$Xval);
}
Try like
$res = array();
foreach($my_arr as $value)
{
$my_var[] = explode(',',$value);
$i = 0;
foreach($my_var as $ky)
{
if($i++ != 0)
$exp_arr[] = $ky;
}
$res[$my_var[0]] = implode(',',$exp_arr);
}
or you can unset like
foreach($my_arr as $value)
{
$my_var[] = explode(',',$value);
$temp = $my_var[0];
unset($my_var[0]);
$res[$temp] = implode(',',$my_var);
}
try this
<?php
$array=array('a,b,c', 'x,y,z');
foreach($array as $key=>$val)
{
$array[substr($val,0,1)]=substr($val,2);
unset($array[$key]);
}
print_r($array);
?>
See Demo

PHP set dynamic array index

I have the following key/value from my $_POST variable:
Array
(
'translations_0_comment' => 'Greetings from UK'
)
What I would like is to set this values to the following array
$data[translations][0][comment] = 'Greetings from UK';
So the idea is that I can have anything in my KEY values, and from that I will populate an array.
Is there any safe way to do this without using eval() ?
All help is appreciated.
UPDATE:
this would be the idea with eval()
foreach ($_POST as $key => $dataValue) {
$a = explode("_", $key);
$builder = '$object';
foreach ($a as $value) {
$builder.='['.$value.']';
}
$builder.=' = '.$dataValue.';';
eval($builder);
}
I think you are looking for this
function set_value($object, $paths, $value, $index){
$key = $paths[$index];
$sub_object = $object[$key];
if (!is_array($sub_object)){
$object[$key] = $value;
}else{
$index = $index+1;
$object[$key] = set_value($sub_object, $paths, $value, $index);
}
return $object;
}
explode() is what you need:
$data = array();
foreach ($postData as $key => $val) {
$explodedKey = explode('_', $key);
$data[$explodedKey[0]][$explodedKey[1]][explodedKey[2]] = $val;
}
No need to use eval().
I think this is what you are looking for
Example
In your form which generate the $_POST data rename the input attribute as follows
<input name="data[translations][0][comment]" />
and now your $_POST['data'] will be an array
$data = array();
foreach ($_POST as $keys => $val) {
$keys_list = explode('_', $keys);
$link = &$data;
foreach ($keys_list as $key) {
$link[$key] = $val;
$link = &$link[$key];
}
}
Try this one sir.
$array = array
(
'TRY_THIS_ONE_SIR_PLEASE_THANKS' => 'Greetings from UK'
);
$array1 = array_keys($array);
$arrValue = array_values($array);
$array1 = explode("_", $array1[0]);
$ctr = count($array1);
for($i=0; $i<$ctr; $i++)
{
$start .= "array(\"".$array1[$i]."\" => ";
$end .=")";
}
$start = $start ."\"".$arrValue[0]."\"".$end;
eval("\$arr = $start;");
print_r($arr);

How do I invert a multidimensional array in PHP

Whats the easiest way to invert a multidimensional array. By invert I mean similar to array_flip.
e.g
[0][5][var_name] = data
[0][3][var_name2] = data2
[1][var_name3] = data3
[0][1][4][var_name4] = data4
inverted would be:
[var_name][0][5] = data
[var_name2][0][3] = data2
[var_name3][1] = data3
[var_name4][0][1][4] = data4
Any ideas?
You could store a list of the keys of all ancestors and when you hit a "leaf" use this list to create the "flipped" version.
<?php
$data = array(
0=>array(
5=>array('var_name' => 'data'),
3=>array('var_name2' => 'data2'),
1=>array(4=>array('var_name4'=>'data4'))
),
1=>array('var_name3'=>'data3')
);
$result = array();
foo($data, $result);
($result['var_name'][0][5] === 'data') or die('1');
($result['var_name2'][0][3] === 'data2') or die('2');
($result['var_name3'][1] === 'data3') or die('3');
($result['var_name4'][0][1][4] === 'data4') or die('4');
echo 'ok';
function foo(array $a, array &$target, $stack=array()) {
foreach($a as $key=>$value) {
if ( is_array($value) ) {
array_push($stack, $key);
foo($value, $target, $stack);
array_pop($stack);
}
else {
$target[$key] = array();
$tmp = &$target[$key];
foreach( $stack as $s ) { // now it's not so stack-ish anymore :-S
$tmp[$s] = array();
$tmp = &$tmp[$s];
}
$tmp = $value;
}
}
}
I couldn't think of an easy way to do this. So I wrote up a really complicated way to do it. Namely:
Take the multidimensional array and flatten it into a list of keys and values.
Reverse the keys.
Unflatten the list to obtain an inverted multidimensional array.
Code
<?php
function print_entries($array, $prekeys = array())
{
foreach ($array as $key => $value)
{
$keys = array_merge($prekeys, array($key));
if (is_array($value))
print_entries($value, $keys);
else
echo '[' . implode('][', $keys) . "] = $value\n";
}
}
function flatten_array($array)
{
$entries = array();
foreach ($array as $key => $value)
{
if (is_array($value))
{
foreach (flatten_array($value) as $subentry)
{
$subkeys = $subentry[0];
$subvalue = $subentry[1];
$entries[] = array(array_merge(array($key), $subkeys), $subvalue);
}
}
else
$entries[] = array(array($key), $value);
}
return $entries;
}
function unflatten_array($entries)
{
$array = array();
foreach ($entries as $entry)
{
$keys = $entry[0];
$value = $entry[1];
$subarray = &$array;
foreach ($keys as $i => $key)
{
if ($i < count($keys) - 1)
{
if (!isset($subarray[$key]))
$subarray[$key] = array();
$subarray = &$subarray[$key];
}
else
$subarray[$key] = $value;
}
}
return $array;
}
function invert_array($array)
{
$entries = flatten_array($array);
foreach ($entries as &$entry)
$entry[0] = array_reverse($entry[0]);
return unflatten_array($entries);
}
$array = array
(
0 => array
(
5 => array('var_name' => 'data'),
3 => array('var_name2' => 'data2'),
1 => array(4 => array('var_name4' => 'data4'))
),
1 => array(0 => array('var_name' => 'data3'))
);
print_entries($array);
echo "\n";
print_entries(invert_array($array));
?>
Output
[0][5][var_name] = data
[0][3][var_name2] = data2
[0][1][4][var_name4] = data4
[1][0][var_name] = data3
[var_name][5][0] = data
[var_name2][3][0] = data2
[var_name4][4][1][0] = data4
[var_name][0][1] = data3
Edit: I noticed now that you don't reverse the keys but you simply move the var_name portion from the end to the front and leave the numerical indices alone. It's easy enough to modify the line in flatten_array where I call array_reverse to re-order the keys in a different way. The core flatten/unflatten logic would not need to be changed. I leave this as an exercise for the reader. :-)

Categories