Multidimensional array from string - php

Let's say I have this string which I want to put in a multidimensional array.
Edit : The number of subfolders in the string are dynamic .. from zero sub folders to 10
<?php
$string ="Folder1/Folder2/Folder3/filename1\n";
$string .=" Folder1/Folder2/Folder3/filename2\n";
$string .=" Folder4/Folder2/Folder3/filename3\n";
?>
I want the following array returned
<?php
Array
(
[Folder1] => Array
(
[Folder2] => Array
(
[Folder3] => Array
(
[0] => filename1
[1] => filename2
)
)
)
[Folder4] => Array
(
[Folder2] => Array
(
[Folder3] => Array
(
[0] => filename3
)
)
)
)
?>
What would be the most efficient way to accomplish this ?
And for the fun of it let's say this array will be send to the other side of the world and it wants to return to a string. How would we do that ?

You could borrow pieces of code from this class (link no longer available), specifically the _processContentEntry method.
Here's a modified version of the method that does the job:
function stringToArray($path)
{
$separator = '/';
$pos = strpos($path, $separator);
if ($pos === false) {
return array($path);
}
$key = substr($path, 0, $pos);
$path = substr($path, $pos + 1);
$result = array(
$key => stringToArray($path),
);
return $result;
}
The output of
var_dump(stringToArray('a/b/c/d'));
Will be
array(1) {
["a"]=>
array(1) {
["b"]=>
array(1) {
["c"]=>
array(1) {
[0]=>
string(1) "d"
}
}
}
}
I suppose that's what you need :)
UPDATE
As per your comment, here's how you can process a string separated by new line characters:
$string = "Folder1/Folder2/Folder3/filename1\n";
$string .= " Folder1/Folder2/Folder3/filename2\n";
$string .= " Folder4/Folder2/Folder3/filename3\n";
// split string into lines
$lines = explode(PHP_EOL, $string);
// trim all entries
$lines = array_map('trim', $lines);
// remove all empty entries
$lines = array_filter($lines);
$output = array();
// process each path
foreach ($lines as $line) {
// split each line by /
$struct = stringToArray($line);
// merge new path into the output array
$output = array_merge_recursive($output, $struct);
}
print_r($output);
P.S.
To convert this array to a string, just call json_encode, however I see no reason to convert it to an array and then back to what it was.

I think this what you want,
$string ="Folder1/Folder2/Folder3/filename1\n";
$string .="Folder1/Folder2/Folder3/filename2\n";
$string .="Folder4/Folder2/Folder3/filename3\n";
$string_array_1 = explode("\n", $string);
$array_need = array();
foreach($string_array_1 as $array_values)
{
if($array_values)
{
$folders = explode("/", $array_values);
$array_need[$folders[0]][$folders[1]][$folders[2]][] = $folders[3];
}
}
print_r($array_need);

This can be solved recursively in another way by taking the items from the beginning of the array and when the last item is reached just return it.
function make_tree( $arr ){
if( count($arr) === 1){
return array_pop( $arr );
}else{
$result[ array_shift( $arr )] = make_tree( $arr ) ;
}
return $result;
}
$string = "Folder1/Folder2/Folder3/filename1\n";
$string .= "Folder1/Folder2/Folder3/filename2\n";
$string .= "Folder4/Folder2/Folder3/filename3\n";
$string = trim( $string );
$files_paths = explode( PHP_EOL, $string);
$result = [];
foreach ($files_paths as $key => $value) {
$parted = explode( '/', $value );
$tree = make_tree( $parted );
$result = array_merge_recursive( $result, $tree );
}
var_dump( $result );

Related

PHP make a multidimensional associative array from key names in a string separated by brackets

I have a string with a variable number of key names in brackets, example:
$str = '[key][subkey][otherkey]';
I need to make a multidimensional array that has the same keys represented in the string ($value is just a string value of no importance here):
$arr = [ 'key' => [ 'subkey' => [ 'otherkey' => $value ] ] ];
Or if you prefer this other notation:
$arr['key']['subkey']['otherkey'] = $value;
So ideally I would like to append array keys as I would do with strings, but that is not possible as far as I know. I don't think array_push() can help here. At first I thought I could use a regex to grab the values in square brackets from my string:
preg_match_all( '/\[([^\]]*)\]/', $str, $has_keys, PREG_PATTERN_ORDER );
But I would just have a non associative array without any hierarchy, that is no use to me.
So I came up with something along these lines:
$str = '[key][subkey][otherkey]';
$value = 'my_value';
$arr = [];
preg_match_all( '/\[([^\]]*)\]/', $str, $has_keys, PREG_PATTERN_ORDER );
if ( isset( $has_keys[1] ) ) {
$keys = $has_keys[1];
$k = count( $keys );
if ( $k > 1 ) {
for ( $i=0; $i<$k-1; $i++ ) {
$arr[$keys[$i]] = walk_keys( $keys, $i+1, $value );
}
} else {
$arr[$keys[0]] = $value;
}
$arr = array_slice( $arr, 0, 1 );
}
var_dump($arr);
function walk_keys( $keys, $i, $value ) {
$a = '';
if ( isset( $keys[$i+1] ) ) {
$a[$keys[$i]] = walk_keys( $keys, $i+1, $value );
} else {
$a[$keys[$i]] = $value;
}
return $a;
}
Now, this "works" (also if the string has a different number of 'keys') but to me it looks ugly and overcomplicated. Is there a better way to do this?
I always worry when I see preg_* and such a simple pattern to work with. I would probably go with something like this if you're confident in the format of $str
<?php
// initialize variables
$str = '[key][subkey][otherkey]';
$val = 'my value';
$arr = [];
// Get the keys we want to assign
$keys = explode('][', trim($str, '[]'));
// Get a reference to where we start
$curr = &$arr;
// Loops over keys
foreach($keys as $key) {
// get the reference for this key
$curr = &$curr[$key];
}
// Assign the value to our last reference
$curr = $val;
// visualize the output, so we know its right
var_dump($arr);
I've come up with a simple loop using array_combine():
$in = '[key][subkey][otherkey][subotherkey][foo]';
$value = 'works';
$output = [];
if(preg_match_all('~\[(.*?)\]~s', $in, $m)) { // Check if we got a match
$n_matches = count($m[1]); // Count them
$tmp = $value;
for($i = $n_matches - 1; $i >= 0; $i--) { // Loop through them in reverse order
$tmp = array_combine([$m[1][$i]], [$tmp]); // put $m[1][$i] as key and $tmp as value
}
$output = $tmp;
} else {
echo 'no matches';
}
print_r($output);
The output:
Array
(
[key] => Array
(
[subkey] => Array
(
[otherkey] => Array
(
[subotherkey] => Array
(
[foo] => works
)
)
)
)
)
Online demo

Is there an easy way to read file contents in array format in PHP?

I am trying to make use of files(.txt) to print logs. Inside the file, it logs an array value which looks like this:
Array
(
[NAME] => John Peters
[AGE] => 24
[COUNTRY] => United States
[EMAIL] => test#test.com
)
So now, I am trying to read the file contents and covert it onto an actual array so that I would be able to reference the value using the array key in a php file, something like:
echo 'Name : ' .$person['NAME'];
echo 'Age: ' .$person['AGE'];
echo 'Country: ' .$person['COUNTRY'];
echo 'Email: ' .$person['EMAIL'];
Is there a predefined php function to do it? Or how will I be able to accomplish what I want. I have tried to use the fread() and fgets() function but it doesn't really accomplish what I want or I might be missing something.
I wrote a quick script for you,
I assumed that in your (files).txt can contain many entries of print_r results e.g.
Array
(
[NAME] => John Peters
[AGE] => 24
[COUNTRY] => United States
[EMAIL] => test#test.com
)
Array
(
[NAME] => John Peters
[AGE] => 24
[COUNTRY] => United States
[EMAIL] => test#test.com
)
This script assumes that your inputs test.txt only contains array that has 1 level (so, it won't work with nested array)
$c = file_get_contents('test.txt');
# Matches all strings that has 'Array(...)' pattern
preg_match_all('#Array[^\)]+\)#', $c, $matches);
$items = array();
foreach($matches[0] as $match) {
# Extracts KEY => VAL patterns from matched text
if (preg_match_all('#\[([^\]]+)\].*?>(.*)#', $match, $array)) {
$items[] = array_combine($array[1], $array[2]);
}
}
# test your results
print_r($items);
you can read it using file_get_contents
Eg:
<?php
$homepage = file_get_contents('abc.txt');
echo $homepage;
?>
Hope it will help :)
I guess #Rezigned and I had the same idea... Here's what I came up with:
<?php
$file = file_get_contents('log.txt');
$file = preg_match_all('/(\s+\[[a-zA-Z0-9]+\]\s+=>\s+.+)\n/', $file, $lines);
$key = array();
$val = array();
foreach ($lines[0] as $line) {
$keys_vals = preg_split('/(\s+=>\s+)/', $line);
$key[] .= preg_replace('/[\[|\]]/', '', $keys_vals[0]);
$val[] .= $keys_vals[1];
}
$line_count = count($lines[0]);
for ($i = 0; $i < $line_count; $i++) {
print $key[$i] . ': ' . $val[$i];
}
There is a function shared by Matt in PHP manual called print_r_reverse, I think it's what you want. The following code is copied from PHP manual print_r function comments section directly.
<?php
function print_r_reverse($in) {
$lines = explode("\n", trim($in));
if (trim($lines[0]) != 'Array') {
// bottomed out to something that isn't an array
return $in;
} else {
// this is an array, lets parse it
if (preg_match("/(\s{5,})\(/", $lines[1], $match)) {
// this is a tested array/recursive call to this function
// take a set of spaces off the beginning
$spaces = $match[1];
$spaces_length = strlen($spaces);
$lines_total = count($lines);
for ($i = 0; $i < $lines_total; $i++) {
if (substr($lines[$i], 0, $spaces_length) == $spaces) {
$lines[$i] = substr($lines[$i], $spaces_length);
}
}
}
array_shift($lines); // Array
array_shift($lines); // (
array_pop($lines); // )
$in = implode("\n", $lines);
// make sure we only match stuff with 4 preceding spaces (stuff for this array and not a nested one)
preg_match_all("/^\s{4}\[(.+?)\] \=\> /m", $in, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
$pos = array();
$previous_key = '';
$in_length = strlen($in);
// store the following in $pos:
// array with key = key of the parsed array's item
// value = array(start position in $in, $end position in $in)
foreach ($matches as $match) {
$key = $match[1][0];
$start = $match[0][1] + strlen($match[0][0]);
$pos[$key] = array($start, $in_length);
if ($previous_key != '') $pos[$previous_key][1] = $match[0][1] - 1;
$previous_key = $key;
}
$ret = array();
foreach ($pos as $key => $where) {
// recursively see if the parsed out value is an array too
$ret[$key] = print_r_reverse(substr($in, $where[0], $where[1] - $where[0]));
}
return $ret;
}
}

show an array inside of an array in a csv file using php

I have created an array using
$processed[$y] = array('source' => $source,
'check total' => number_format($checkTotal, 2, '.', ''),//($rows['total'], 2, '.', ''),
'check number' => $num,
'table' => $invTable,
'skus' => $skuArray,
'check amount' => number_format($amount, 2, '.', '')
);
$y++;
My $skuArray is an array that contains all of the sku's that are associated with a specific check number. I am attempting to have it displayed like:
source check total check number table skus check amount
MNC 152.32 649 inv_temp 10198547 152.32
10195874
so it will list all of the sku's attached to a specific check nuimber before it lists the next item.
Here is my function to convert $processed to a csv file:
function to_csv( $array ) {
$csv = "";
if (count($array) == 0) return "No Processed checks found";
## Grab the first element to build the header
$arr = array_pop( $array );
$temp = array();
foreach( $arr as $key => $data ) {
$temp[] = $key;
}
$csv = implode( ',', $temp ) . "\r\n";
## Add the data from the first element
$csv .= to_csv_line( $arr );
## Add the data for the rest
foreach( $array as $arr ) {
$csv .= to_csv_line( $arr );
}
return $csv;
}
function to_csv_line( $array ) {
$temp = array();
foreach( $array as $elt ) {
$temp[] = '"' . addslashes( $elt ) . '"';
}
$string = implode( ',', $temp ) . "\r\n";
return $string;
}
How can I accomplish this? I have tried using array('skus=>$skuArray), but it just gave me "Array" in the results.
UPDATE: Here is what the array looks like when I do a var_dump($skuArray)
array(1075) { [0]=> string(8) "10182997" [1]=> string(8) "10190313" [2]=> string(8) "10190314" [3]=> string(8) "10190315" etc.
I've provided a solution that is untested, so use at your own discretion.
I've done my best to explain everything through comments in the code.
Remove the first sku value from the sku array, assign it to the first line.
Add additional skus to a temporary array based on the line keys.
Check for temporary sku array, and create the additional lines from it.
Your final to_csv function will look something like this:
function to_csv( $array ) {
$csv = "";
if (count($array) == 0) return "No Processed checks found";
## Grab the first element to build the header
$arr = $array[0];
$temp = array();
foreach( $arr as $key => $data ) {
$temp[] = $key;
}
$csv = implode( ',', $temp ) . "\r\n";
## Process each line
foreach( $array as $arr ) {
## Check for multiple sku values. Create a temporary array for them to add them after this line.
if(isset($arr['skus']) && is_array($arr['skus']))
{
//Remove the first value (since we only need it for the actual line item)
$sku_value = $arr['skus'][0];
unset($arr['skus'][0]);
//Create temporary lines for each sku
$temp_sku_arrays = array();
foreach($arr['skus'] as $sku)
{
$sku_array = array();
foreach($arr as $key => $value)
{
//Set only the sku key with a value.
$sku_array[$key] = ($key == 'skus' ? $sku : '');
}
$temp_sku_arrays[] = $sku_array;
}
//Set the first line to the first sku value.
$arr['skus'] = $sku_value;
}
$csv .= to_csv_line( $arr );
//Check for additional sku lines, then add them
if(isset($temp_sku_arrays) && is_array($temp_sku_arrays))
{
foreach($temp_sku_arrays as $sku_array)
{
$csv .= to_csv_line( $sku_array );
}
unset($temp_sku_arrays);
}
}
return $csv;
}
I think CSV is not well suited for what you are about to do. I would use json or xml. However, you could choose a separator different from the csv sepator to represent an array, Like this:
foo,bar1;bar2;bar3,...
what would represent the following record:
$record = array (
'foo',
array ('bar1', 'bar2', 'bar3')
);

PHP split string containing html tags and split string into array

Question
i have string like this $str="a|apple||b|bat||c|cat||d|dog";
from the above string i want to create a array dynamically n that newly created array shud look like this Array
(
[a] => apple
[b] => bat
[c] => cat
[d] => dog
)
Question
i have html string like this
$html_string="<div>Content Div1</div>
<div>Content Div2</div>
<div>Content Div3</div>";
how can i get 3rd DIV ,resulting answer should be like this
$ans="<div>Content Div3</div>" ;
Please anyone help me
for the first one
$str = "a|apple||b|bat||c|cat||d|dog";
$new_array = array();
$my_array = explode("||", $str);
$my_array = array_filter($my_array);
foreach ($my_array as $mine) {
$my = explode("|", $mine);
$new_array[$my[0]] = $my[1];
}
print_r($new_array);
// Output
Array
(
[a] => apple
[b] => bat
[c] => cat
[d] => dog
)
**for second**
$html_string = "<div>Content Div1</div><div>Content Div2</div><div>Content Div3</div>";
$new_arr = explode("</div>", $html_string);
$my_data = $new_arr[2] . '</div>';
print_r($my_data);
// Output
<div>Content Div3</div>
Try this:
First
$str = "a|apple||b|bat||c|cat||d|dog";
$my_array = explode("||", $str);
$finalArr=array();
foreach($my_array as $my_arr)
{
$myar = explode("|", $my_arr);
$finalArr[$myar[0]]=$myar[1];
}
print_r($finalArr);
For Second
$html_string="<div>Content Div1</div><div>Content Div2</div><div>Content Div3</div>";
$secondArray = explode('</div>', $html_string);
echo $res = $secondArray[2] . "</div>";
Test it on http://writecodeonline.com/php/
try this:
1st Answer:
<?php
$str="a|apple||b|bat||c|cat||d|dog";
$parentArray = explode('||', $str);
$finalArray = array();
foreach($parentArray as $parentKey=>$parentValue)
{
$childArray = explode('|', $parentValue);
$finalArray[$childArray[0]] = $childArray[1];
}
echo "<pre>";
print_r($finalArray);
?>
2nd Answer
<?php
$html_string="<div>Content Div1</div>
<div>Content Div2</div>
<div>Content Div3</div>";
$finalArray = explode('</div>', $html_string);
$resultRequired = $finalArray[2] . "</div>";
?>
For your first question:
$tmp_array = explode( '||', $str );
$str_array = array();
foreach( $tmp_array as $value ){
$tmp = explode( '|', $value );
$str_array[ $tmp[0] ] = $tmp[1];
}
For your second question
$html_array = array();
$pattern = '/\<div\>.*\<\/div\>/i';
if( preg_match_all( $pattern, $html_string, $matches ) ) {
$html_array = $matches[0];
}
Which will make:
<div>Content Div3</div>
Be in $html_array[2] if any matches are found.

creating dynamic array in php

I have following records in text file, need to extract that record form text file and treat them as seperate array variables
r1=(1,2,3)|r2=(4,5,6)|r3=(1,2,3,4,5,7)|rn=(9,6,7,8) seperated by pipe(|)
I need to represent that as array use seperately like below
$r1= Array
(
[0] => 1
[1] => 2
[2] => 3
)
$r2=Array
(
[0] => 4
[1] => 5
[2] => 6
)
I have no idea how to do it, is it possible in php?
Just a plain regular expression to break up the string, followed by an explode on each group:
if (preg_match_all('#(\w+)=\(([\d,]*)\)#', $s, $matches)) {
foreach ($matches[2] as $i => $groups) {
$group_name = $matches[1][$i];
$$group_name = array_map('intval', explode(',', $groups));
}
}
print_r($r1);
print_r($r3);
print_r($rn);
You can use Eval
//Assuming you can pull the content from text file using fread
$temp = "r1=(1,2,3)|r2=(4,5,6)";
$temp=str_replace("=","=array",$temp);
$split=explode("|",$temp);
echo "<pre>";
foreach($split as $k=>$v){
$v="$".$v.";";
//Evaluate a string as PHP code .i.e You will get r1,r2 as a variable now which is array
eval($v);
}
print_r($r1);
print_r($r2);
$data = "r1=(1,2,3)|r2=(4,5,6)|r3=(1,2,3,4,5,7)|rn=(9,6,7,8)";
$arr = explode("|", $data);
$finArray = array();
foreach($arr as $key=>$value)
{
$single = explode('(', $value);
$finArray[] = explode(',', str_replace(')', '', $single[1]));
}
print_r($finArray);
can be done as:
$string="r1=(1,2,3)|r2=(4,5,6)|r3=(1,2,3,4,5,7)|rn=(9,6,7,8)";
$string=str_repla("r1=","",$string);
$yourArray=explode('|', $string);
This code will help you:--
<?php
$file = "/tmp/file1.txt"; // this is your file path
$f = fopen($file, "r");
while ( $line = fgets($f, 1000) ) {
print $line;
$a=explode('|',$line);
print_r($a); // I have explode based on | for you...
foreach($a as $key=>$value)
{
print_r($value);
}
fclose($file);
}
?>
""or""
$a="r1=(1,2,3)|r2=(4,5,6)|r3=(1,2,3,4,5,7)|rn=(9,6,7,8)";
$a=explode('|',$a);
print_r($a);
<?php
$file = "file.txt";
$f = fopen($file, "r");
while ( $line = fgets($f, 1000) ) {
$str = $line;
}
$str1 = explode("|",$str);
foreach($str1 as $temp) {
$str2 = explode("=",$temp);
$data[$str2[0]] = explode(",",trim($str2[1],"()"));
}
echo '<pre>';
print_r($data);
echo '</pre>';
?>
This will do your job.

Categories