I need to read nested arrays without knowing how the array will look.
For example;
$data = array(
'Data1_lvl1' => array(
'Data1_lvl2' => "value",
'Data2_lvl2' => array(
'Data1_lvl3' => "value"
)
),
'Data2_lvl1' => 'value'
);
Needs to be formatted to strings like:
Data1_lvl1/Data1_lvl2/
Data1_lvl1/Data2_lvl2/Data1_lvl3/
Data2_lvl1/
But the array can be of any size with any number of nested arrays inside it.
$data = array(
'Data1_lvl1' => array(
'Data1_lvl2' => "value",
'Data2_lvl2' => array(
'Data1_lvl3' => "value"
)
),
'Data2_lvl1' => 'value'
);
function printArray($array)
{
foreach ($array as $key=>$value)
{
echo $key.'/';
if (is_array($value))
{
printArray($value);
} else {
echo '<br>';
}
}
}
printArray($data);
If you want to output only the name of array elements then this recursive function will do the trick.
Your data:
$data = array(
'Data1_lvl1' => array(
'Data1_lvl2' => "value",
'Data2_lvl2' => array(
'Data1_lvl3' => "value"
)
),
'Data2_lvl1' => 'value'
);
Function:
function array2str($array, $str) {
foreach($array as $key => $val) {
if (is_array($val) ) {
$str .= $key . '/';
array2str($val, $str);
}
}
echo $str.'<br />';
return $str;
}
array2str($data);
As you can see the script does ECHO in itself with <br /> to break the line when viewing results in a browser.
One way would to walk recursively through array with function similar to this:
<?php
function f($d, $str = '') {
foreach ($d as $key => $val) {
if (is_array($val)) f($val, $str . '/' . $key); // If this element is array parse next level
else print_r($str . '/' . $key . '/'); // Output current string or do what you need to do with it..
}
}
$data = array(
'Data1_lvl1' => array(
'Data1_lvl2' => "value",
'Data2_lvl2' => array(
'Data1_lvl3' => "value"
)
),
'Data2_lvl1' => 'value'
);
f($data);
with that function:
<?php
function print_tree ($data, $prefix = '', &$index = 1) {
foreach($data as $key => $datum) {
echo $index++ . '. ' . ($new_prefix = $prefix . $key . '/') . PHP_EOL;
if (is_array($datum)) {
print_tree ($datum, $new_prefix, $index);
}
}
}
I get
Data1_lvl1/
Data1_lvl1/Data1_lvl2/
Data1_lvl1/Data2_lvl2/
Data1_lvl1/Data2_lvl2/Data1_lvl3/
Data2_lvl1/
Related
I have an array in the following format (each child array has parent's key as a prefix):
$input = array(
'seo_text' => array(
'seo_text_title' => '',
'seo_text_description' => '',
'seo_text_button' => array(
'seo_text_button_text' => '',
'seo_text_button_url' => '',
'seo_text_button_new_tab_enabled' => '',
),
),
);
I want to convert it into the following format:
$input = array(
'seo_text' => array(
'title' => '',
'description' => '',
'button' => array(
'text' => '',
'url' => '',
'new_tab_enabled' => '',
),
),
);
I'm trying to write a recursive function, but it's not working the way it's suppose to be working.
A solution:
function removeKeyPrefix(array $array, string $prefix = ''): array
{
$newArray = [];
$prefixLength = strlen($prefix);
foreach ($array as $key => $value) {
if (substr($key, 0, $prefixLength) === $prefix) {
$newKey = substr($key, $prefixLength);
} else {
$newKey = $key;
}
$newArray[$newKey] = is_array($value) ? removeKeyPrefix($value, $key.'_') : $value;
}
return $newArray;
}
$input = removeKeyPrefix($input);
Online demo on 3v4l
function sanitizeKeys(array $items, $previousKey = '') : array
{
$previousKey .= "_";
return array_reduce(
array_keys($items),
function($result, $key) use ($previousKey, $items) {
$newKey = (0 === strpos($key, $previousKey)) ? substr_replace($key, '', 0, strlen($previousKey)) : $key;
$result[$newKey] = is_array($items[$key]) ? sanitizeKeys($items[$key], $key) : $items[$key];
return $result;
}, []
);
};
sanitizeKeys($input);
Make a function to change last occurrence in the slug
function fun($array,$slug){
foreach($array as $key=>$val){
$last = end(explode($slug,$key));
if(is_array($val)){
$val = fun($val,$key."_");
}
$array[$last] = $val;
unset($array[$key]);
}
return $array;
}
$input["seo_text"] = fun($input["seo_text"],"seo_text_");
print_r($input);
Live demo : https://eval.in/934155
Output is
Array
(
[seo_text] => Array
(
[title] =>
[description] =>
[button] => Array
(
[text] =>
[url] =>
[new_tab_enabled] =>
)
)
)
For if you have many element in second level use foreach to call function like below
foreach($input as $key=>$val){
$input[$key] = fun($val,$key."_");
}
print_r($input);
https://eval.in/934156
I am trying to convert a multidimensional array into a string.
Till now I have been able to convert a pipe delimited string into an array.
Such as:
group|key|value
group|key_second|value
Will render into the following array:
$x = array(
'group' => array(
'key' => 'value',
'key_second' => 'value'
),
);
However, now I want it to be the other way around, where a multidimensional array is provided and I want to convert it to a pipe delimited string just like in the first code example.
Any ideas how to do this ?
PS: Please do note that the array can dynamically have any depth.
For example:
$x['group']['sub_group']['category']['key'] = 'value'
Translates to
group|sub_group|category|key|value
I have created my own function:
This should have no problem handling even big arrays
function array_to_pipe($array, $delimeter = '|', $parents = array(), $recursive = false)
{
$result = '';
foreach ($array as $key => $value) {
$group = $parents;
array_push($group, $key);
// check if value is an array
if (is_array($value)) {
if ($merge = array_to_pipe($value, $delimeter, $group, true)) {
$result = $result . $merge;
}
continue;
}
// check if parent is defined
if (!empty($parents)) {
$result = $result . PHP_EOL . implode($delimeter, $group) . $delimeter . $value;
continue;
}
$result = $result . PHP_EOL . $key . $delimeter . $value;
}
// somehow the function outputs a new line at the beginning, we fix that
// by removing the first new line character
if (!$recursive) {
$result = substr($result, 1);
}
return $result;
}
Demo provided here http://ideone.com/j6nThF
You can also do this using a loop like this:
$x = array(
'group' => array(
'key' => 'value',
'key_second' => 'value'
)
);
$yourstring ="";
foreach ($x as $key => $value)
{
foreach ($x[$key] as $key2 => $value2)
{
$yourstring .= $key.'|'.$key2.'|'.$x[$key][$key2]."<BR />";
}
}
echo $yourstring;
Here is a working DEMO
This code should do the thing.
You needed a recursive function to do this. But be careful not to pass object or a huge array into it, as this method is very memory consuming.
function reconvert($array,$del,$path=array()){
$string="";
foreach($array as $key=>$val){
if(is_string($val) || is_numeric($val)){
$string.=implode($del,$path).$del.$key.$del.$val."\n";
} else if(is_bool($val)){
$string.=implode($del,$path).$del.$key.$del.($val?"True":"False")."\n";
} else if(is_null($val)){
$string.=implode($del,$path).$del.$key.$del."NULL\n";
}else if(is_array($val)=='array') {
$path[]=$key;
$string.=reconvert($val,$del,$path);
array_pop($path);
} else {
throw new Exception($key." has type ".gettype($val).' which is not a printable value.');
}
}
return $string;
}
DEMO: http://ideone.com/89yLLo
You can do it by
Look at serialize and unserialize.
Look at json_encode and json_decode
Look at implode
And Possible duplicate of Multidimensional Array to String
You can do this if you specifically want a string :
$x = array(
'group' => array(
'key' => 'value',
'key_second' => 'value'
),
'group2' => array(
'key2' => 'value',
'key_second2' => 'value'
),
);
$str='';
foreach ($x as $key=>$value)
{
if($str=='')
$str.=$key;
else
$str.="|$key";
foreach ($value as $key1=>$value1)
$str.="|$key1|$value1";
}
echo $str; //it will print group|key|value|key_second|value|group2|key2|value|key_second2|value
I'm trying to write a function that takes a multi-dimensional array as input and outputs a multi-line string of keys like the following
['key']['subkey']
['key']['another_subkey']
['key']['another_subkey']['subkey_under_subkey']
['key']['yet_another_subkey']
['another_key']['etc']
Here is my attempt. It has problems when you get to the second level.
function get_array_keys_as_string($array){
$output = "";
foreach($array as $k => $v){
if(is_array($v)){
$string = get_array_keys_as_string($v);
$prepend = "['$k']";
$string = $prepend.str_replace("\n","\n".$prepend, $string);
$output .= $string;
}
else{
$output .= "['$k']\n";
}
}
return $output;
}
I know I need a recursive function, but so far my attempts have come up short.
To get the exact output you asked for use the following:
$arr = array(
"key" => array(
"subkey" => 1,
"another_subkey" => array(
"subkey_under_subkey" => 1
),
"yet_another_subkey" => 1
),
"another_key" => array(
"etc" => 1
)
);
function print_keys_recursive($array, $path = false) {
foreach($array as $key=>$value) {
if(!is_array($value)) {
echo $path."[".$key."]<br/>";
} else {
if($path) {
echo $path."[".$key."]<br/>";
}
print_keys_recursive($value, $path."[".$key."]");
}
}
return;
}
print_keys_recursive($arr);
Output:
[key][subkey]
[key][another_subkey]
[key][another_subkey][subkey_under_subkey]
[key][yet_another_subkey]
[another_key][etc]
Not sure how you want the output since you have not provided an example array, just the result, but here is an example based on the following array,
$array = array(
"key" => array(
"subkey" => 1,
"another_subkey" => array("2", "subkey_under_subkey" => 3),
"yet_another_subkey" => 4
),
"another_key" => array("etc"),
"last_key" => 0
);
Using the following function,
function recursive_keys($arr, $history = NULL)
{
foreach ($arr as $key => $value)
{
if (is_array($value))
recursive_keys($value, $history."['".$key."']");
else
echo $history."['".$key."']\n";
}
}
Output of recursive_keys($array) is,
['key']['subkey']
['key']['another_subkey']['0']
['key']['another_subkey']['subkey_under_subkey']
['key']['yet_another_subkey']
['another_key']['0']
['last_key']
Try this
function arrayMultiKeys($array,$depth = 0){
foreach($array as $k=>$v){
echo "['".$k."']";
if(is_array($v)){
arrayMultiKeys($v,$depth + 1);
}
if($depth == 0 ){
echo "<br>";
}
}
}
I searched in Google and consulted the PHP documentation, but couldn't figure out how the following code works:
$some='name=Licensing Module;nextduedate=2013-04-10;status=Active|name=Test Addon;nextduedate=2013-04-11;status=Active';
function getActiveAddons($somet) {
$addons = array( );
foreach ($somet as $addon) {
if ($addon['status'] == 'Active') {
$addons[] = $addon['name'];
continue;
}
}
return $addons;
}
echo (count( getActiveAddons( $some ) ) ? implode( '<br />', getActiveAddons( $some ) ) : 'None');
The code always echo's None.
Please help me in this.
I don't know where you got this code from but you've initialized $some the wrong way. It is expected as an array like this:
$some = array(
array(
'name' => 'Licensing Module',
'nextduedate' => '2013-04-10',
'status' => 'Active'
),
array(
'name' => 'Test Addon'
'nextduedate' => '2013-04-11',
'status' => 'Active'
)
);
I guess the article you've read is expecting you to parse the original string into this format.
You can achieve this like this:
$string = 'name=Licensing Module;nextduedate=2013-04-10;status=Active|name=Test Addon;nextduedate=2013-04-11;status=Active';
$result = array();
foreach(explode('|', $string) as $record) {
$item = array();
foreach(explode(';', $record) as $column) {
$keyval = explode('=', $column);
$item[$keyval[0]] = $keyval[1];
}
$result[]= $item;
}
// now call your function
getActiveAddons($result);
$some is not an array so foreach will not operate on it. You need to do something like
$some = array(
array(
'name' => 'Licensing Module',
'nextduedate' => '2013-04-10',
'status' => 'Active'
),
array(
'name' => 'Test Addon',
'nextduedate' => '2013-04-11',
'status'=> 'Active'
)
);
This will create a multidimensional array that you can loop through.
function getActiveAddons($somet) {
$addons = array( );
foreach ($somet as $addon) {
foreach($addon as $key => $value) {
if ($key == 'status' && $value == 'Active') {
$addons[] = $addon['name'];
continue;
}
}
}
return $addons;
}
First, your $some variable is just a string. You could parse the string into an array using explode(), but it's easier to just start as an array:
$some = array(
array(
"name" => "Licensing Module",
"nextduedate" => "2013-04-10",
"status" => "Active",
),
array(
"name" => "Test Addon",
"nextduedate" => "2013-04-11",
"status" => "Active",
)
);
Now, for your function, you are on the right track, but I'll just clean it up:
function getActiveAddons($somet) {
if (!is_array($somet)) {
return false;
}
$addons = array();
foreach ($somet as $addon) {
if ($addon['status'] == 'Active') {
$addons[] = $addon['name'];
}
}
if (count($addons) > 0) {
return $addons;
}
return false;
}
And finally your output (you were calling the function twice):
$result = getActiveAddons($some);
if ($result === false) {
echo "No active addons!";
}
else {
echo implode("<br />", $result);
}
Right now i got an array which has some sort of information and i need to create a table from it. e.g.
Student{
[Address]{
[StreetAddress] =>"Some Street"
[StreetName] => "Some Name"
}
[Marks1] => 100
[Marks2] => 50
}
Now I want to create database table like which contain the fields name as :
Student_Address_StreetAddress
Student_Address_StreetName
Student_Marks1
Student_Marks2
It should be recursive so from any depth of array it can create the string in my format.
You can use the RecursiveArrayIterator and the RecursiveIteratorIterator (to iterate over the array recursively) from the Standard PHP Library (SPL) to make this job relatively painless.
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($arr));
$keys = array();
foreach ($iterator as $key => $value) {
// Build long key name based on parent keys
for ($i = $iterator->getDepth() - 1; $i >= 0; $i--) {
$key = $iterator->getSubIterator($i)->key() . '_' . $key;
}
$keys[] = $key;
}
var_export($keys);
The above example outputs something like:
array (
0 => 'Student_Address_StreetAddress',
1 => 'Student_Address_StreetName',
2 => 'Student_Marks1',
3 => 'Student_Marks2',
)
(Working on it, here is the array to save the trouble):
$arr = array
(
'Student' => array
(
'Address' => array
(
'StreetAddress' => 'Some Street',
'StreetName' => 'Some Name',
),
'Marks1' => '100',
'Marks2' => '50',
),
);
Here it is, using a modified version of #polygenelubricants code:
function dfs($array, $parent = null)
{
static $result = array();
if (is_array($array) * count($array) > 0)
{
foreach ($array as $key => $value)
{
dfs($value, $parent . '_' . $key);
}
}
else
{
$result[] = ltrim($parent, '_');
}
return $result;
}
echo '<pre>';
print_r(dfs($arr));
echo '</pre>';
Outputs:
Array
(
[0] => Student_Address_StreetAddress
[1] => Student_Address_StreetName
[2] => Student_Marks1
[3] => Student_Marks2
)
Something like this maybe?
$schema = array(
'Student' => array(
'Address' => array(
'StreetAddresss' => "Some Street",
'StreetName' => "Some Name",
),
'Marks1' => 100,
'Marks2' => 50,
),
);
$result = array();
function walk($value, $key, $memo = "") {
global $result;
if(is_array($value)) {
$memo .= $key . '_';
array_walk($value, 'walk', $memo);
} else {
$result[] = $memo . $key;
}
}
array_walk($schema, 'walk');
var_dump($result);
I know globals are bad, but can't think of anything better now.
Something like this works:
<?php
$arr = array (
'Student' => array (
'Address' => array (
'StreetAddress' => 'Some Street',
'StreetName' => 'Some Name',
),
'Marks1' => array(),
'Marks2' => '50',
),
);
$result = array();
function dfs($data, $prefix = "") {
global $result;
if (is_array($data) && !empty($data)) {
foreach ($data as $key => $value) {
dfs($value, "{$prefix}_{$key}");
}
} else {
$result[substr($prefix, 1)] = $data;
}
}
dfs($arr);
var_dump($result);
?>
This prints:
array(4) {
["Student_Address_StreetAddress"] => string(11) "Some Street"
["Student_Address_StreetName"] => string(9) "Some Name"
["Student_Marks1"] => array(0) {}
["Student_Marks2"] => string(2) "50"
}
function getValues($dataArray,$strKey="")
{
global $arrFinalValues;
if(is_array($dataArray))
{
$currentKey = $strKey;
foreach($dataArray as $key => $val)
{
if(is_array($val) && !empty($val))
{
getValues($val,$currentKey.$key."_");
}
else if(!empty($val))
{
if(!empty($strKey))
$strTmpKey = $strKey.$key;
else
$strTmpKey = $key;
$arrFinalValues[$strTmpKey]=$val;
}
}
}
}