I did this code:
index.php:
$series = array(
"a" => array(
"b" => array(
"FOLD", "more_arrays.php"
),
"b2" => array(
)
)
);
function pre($a) { print "<pre>"; print_r($a); print "</pre>"; }
$string = "a,,,b";
$all_directions = explode(",,,", $string);
$all_directions = array_map("trim", $all_directions);
$b = ""; $g = 0;
foreach($all_directions as $v)
{
$b .= "['".str_replace(array("[", "]", "'", "\""), null, $v)."']";
$g++;
}
#eval('$where = $series'.$b.';');
if(isset($where[0]) && $where[0] == "FOLD")
{
// a[series], b[series], c[new_array]
require_once("./more_folders/".$where[1]);
print $g;
}
for($i = 0; $i <= sizeof($where); $i++)
{
}
pre($where);
more_array.php:
$series_in = array(
"c" => array(
"d" => array(
"bla" => array(),
"hey" => array(),
"ha" => array()
),
"d2" => array(
)
),
"c2" => array(
)
)
At $string I define which "folder" I want to see, for example if I write $string = "a"; it will show all the arrays inside "a".
key = the name of the folder, value = the subfolders inside the folder and those array.
Now: Because it's going to be a huge array, I want to separate it to many arrays.
If you see at the code, $series[a][b] direct lead to another array.
Now if I do $string = "a,,,b"; I want to see: "c" and "c2"
and if I do $string = "a,,,b,,,c"; I want to see: "d", "d2"
and if I do $string = "a,,,b,,,c,,,d"; I want to see all inside d ( "bla", "hey", "ha" ..)
How can I do this?
I'll bite...
You seem to have most of the parts. Basically you need to put them together in a loop.
You've $string and $series. Then you split $string into your $all_directions. Loop thru $all_directions, each time diving down into the array $series = $series[$all_directions[$i]]; When you've done the last $all_directions return $series (but watch for running out of $series, return null, or false if you're sure that would be an error).
The only other thing is any time $series[$all_directions[$i]] is the special "FOLD" entry then first load the file and assign it on-the-fly something like
include ...;
$series[$all_directions[$i]] = $series_in;
You don't want and don't need eval() and the loop is better using for because you need to check "FOLD" in the key (I'd also say use a recursive function but you said the array can be very big so it might hurt performance).
Related
I got a pretty tricky problem... I'm making a programm that will get the array from another php file, will sort it and will overwrite the php file with the new array. I'm making some test on 2 php files. One is index.php and the other one is PHPPage2.php ( thats the one with the arrays ).
Here is the code : PHPPage2.php
<?php
$array = array(
"d" => "lemon",
"a" => "orange",
"b" => "banana",
"c" => "apple"
);
$fruits = array(
"d" => "lemon",
"a" => "orange",
"b" => "banana",
"c" => "apple"
);
?>
And here is index.php
$NomArray = array();
$lines = array(); #That's an array of lines, it gets all line of the file
$fp = fopen("Test/TextFile.txt", "r");
while (!feof($fp))
{
$line = fgets($fp);
#Lookinf for an "array" variable
for($i = 0; $i < strlen($line); $i++)
{
if($line[$i] == 'a' and $line[$i-1] <> '$' and $line[$i+1] == 'r' and $line[$i+2] == 'r' and $line[$i+3] == 'a' and $line[$i+4] == 'y')
{
$line = trim($line);
$lines[]=$line;
$NomVariable = "";
#looking for the name fo the variable
for($i = 0; $i < strlen($line); $i++)
{
# if there is a $, it's a variable
if($line[$i] == '$')
{
# we take all char until that we hit a "=" or " "
for($j = $i; $j < strlen($line); $j++)
{
if($line[$j] <> '=' and $line[$j] <> ' ')
{
$NomVariable = $NomVariable . $line[$j];
}
else
{
break;
}
}
}
}
#We put the name of the variable in a array
$NomArray[] = $NomVariable;
}
}
}
fclose($fp);
#We include PHPPage2.php
include "Test/PHPPage2.php";
# a for loop to get all variable name HERE IS MY PROBLEM
for($i = 0; $i < count($NomArray); $i++)
{
# I wanna use what is inside $NomArray[$i] as the name of a dynamic variable
$NomVar = $NomArray[$i];
/*
I want to sort the array that as the name of $NomArray[$i],
But I dont know why, when i = 0 ${$NomVar)} is suppose to be equal to $array...
That seems logic to me, but it dosent work...
*/
asort(${$NomVar});
foreach (${$NomVar} as $key => $val)
{
echo "\"$key\" => \"$val\", \n";
}
}
i've also looked at http://php.net//manual/en/language.variables.variable.php but that dosen't work :(
Thanks in advance for your help!
(Sorry if my english isn't the best)
since you've declared the two arrays as globals, you can cheat by using
$GLOBALS[$NomVar]
which will give you the array you are looking for. However, a smarter solution would be to nest both arrays inside another array
<?php
$choices = array('array'=> array(
"d" => "lemon",
"a" => "orange",
"b" => "banana",
"c" => "apple"
),'fruits' => array(
"d" => "lemon",
"a" => "orange",
"b" => "banana",
"c" => "apple"
));
?>
so you could retrieve the arrays by using their keys
$choices[$NomVar]
I have to create a array dynamically like I have a method which will pass keys and based on those keys I need to create arrays inside them
Format will be like-
{
"TEST1":{
"140724":[
{
"A":"1107",
"B":4444,
"C":"1129",
"D":"1129"
},
{
"A":"1010",
"B":2589,
"C":"1040",
"D":"1040"
}
],
"140725":[
]
}
}
So how should I frame this logic inside for loop. I am new to php so formatting the same creating trouble.
$json_Created = array("TEST1" => array());
foreach($val as $key=>$value){
array_push($json_created,array($key = array()));
}
The entire array is dynamic, so like I have 140724 ,,, till 140731 (actually date format yymmdd), any amount if numbers can be considered. SO that part is dynamic moreover some dates may be wont have any values and some will have.
So my main point is to develop that logic so that irrespective the
number of inputs , my array formation must be intact.
You can use json_encode with array to do so
$array = array(
"TEST1" => array(
"140724" => array(
array(
"A" => "1107",
"B" => "4444",
"C" => "1129",
"D" => "1129"
),
array (
"A" => "1010",
"B" => "2589",
"C" => "1040",
"D" => "1040"
)
),
"140725" => array(
)
)
);
echo json_encode($array);
Another way to construct array is
$array = array();
$array["TEST1"]["140724"][] = array(
"A" => "1107",
"B" => "4444",
"C" => "1129",
"D" => "1129"
);
$array["TEST1"]["140724"][] = array (
"A" => "1010",
"B" => "2589",
"C" => "1040",
"D" => "1040"
);
$array["TEST1"]["140725"] = array();
echo json_encode($array);
Finally managed to write the code-
$keys_content = array("starttime", "id", "duration", "endtime");
$dates = array();//140724,140725,140726140727
$mainID =“TEST1”;
$arraySuperMain = array();
$arrayMain = array();
for ($j = 0; $j < count($dates); $j++) {
$array_main = array();
$subset = array();
for ($i = 0; $i < count($keys_content); $i++) {
$key = $keys_content[$i];
$subset = array_push_assoc($subset, $key, "Value".$i);
}
$array_main = array_push_assoc($array_main, $dates[$j], $subset);
array_push($arrayMain, $array_main);
}
$createdJSON = array_push_assoc($arraySuperMain, $mainID, $arrayMain);
public static function array_push_assoc($array, $key, $value) {
$array[$key] = $value;
return $array;
}
I made a small function to parse and get elements from a multidimensional array by a string written in a Unix-like path syntax.
function array_get($path, &$array) {
$keys = preg_split('/[\/\\\]+/', $path, null, PREG_SPLIT_NO_EMPTY);
$current = trim(array_shift($keys));
if (is_array($array) && array_key_exists($current, $array)) {
$path = implode("/", $keys);
if (empty($path)) {
// (Place the code here, see below)
return $array[$current];
}
return array_get($path, $array[$current]);
}
return false;
}
So if I got a simple array like this
$arr = array(
"A" => array(
"X" => array(),
"Y" => array(),
"Z" => array()
),
"B" => array(
"X" => array(),
"Y" => array(),
"Z" => array()
),
"C" => array(
"X" => array(),
"Y" => array(),
"Z" => array()
)
);
and I wish to fill it within some entries like these
$arr['A']['Z'][] = "foo";
$arr['A']['Z'][] = "bar";
I would do the same job using the following statements:
$var = array_get("A/Z", $arr);
$var[] = "foo";
$var[] = "bar";
But something went wrong.
If you try to run the code you will notice that going out of the local scope the references to the passed array will be lost.
If you wish to run a test, you can replace the placeholder comment line inside the function with these two code lines:
$array[$current][] = "foo";
$array[$current][] = "bar";
then you will see that the function would perform actually its own job.
Is there a way to maintain the references in output?
From the documentation, you can specify you want to return a reference by using the & character before the function name AND the function call.
<?php
function &foo(&$arr) {
return $arr[0];
}
$a = [[]];
$b = &foo($a);
$b[0] = 'bar';
print_r($a); /* outputs [ [ 'bar' ] ] */
You can return references.
But I find your approach really cumbersome, and it will lead to misbehaviours / maintainability / readability issues very soon.
I am having trouble figuring out a way to simply parse a string input and find the correct location within a multidimensional array.
I am hoping for one or two lines to do this, as the solutions I have seen rely on long (10-20 line) loops.
Given the following code (note that the nesting could, in theory, be of any arbitrary depth):
function get($string)
{
$vars = array(
'one' => array(
'one-one' => "hello",
'one-two' => "goodbye"
),
'two' => array(
'two-one' => "foo",
'two-two' => "bar"
)
);
return $vars[$string]; //this syntax isn't required, just here to give an idea
}
get("two['two-two']"); //desired output: "bar". Actual output: null
Is there a simple use of built-in functions or something else easy that would recreate my desired output?
Considering $vars being your variables you would like to get one['one-one'] or two['two-two']['more'] from (Demo):
$vars = function($str) use ($vars)
{
$c = function($v, $w) {return $w ? $v[$w] : $v;};
return array_reduce(preg_split('~\[\'|\'\]~', $str), $c, $vars);
};
echo $vars("one['one-one']"); # hello
echo $vars("two['two-two']['more']"); # tea-time!
This is lexing the string into key tokens and then traverse the $vars array on the keyed values while the $vars array has been turned into a function.
Older Stuff:
Overload the array with a function that just eval's:
$vars = array(
'one' => array(
'one-one' => "hello",
'one-two' => "goodbye"
),
'two' => array(
'two-one' => "foo",
'two-two' => "bar"
)
);
$vars = function($str) use ($vars)
{
return eval('return $vars'.$str.';');
};
echo $vars("['one']['one-two']"); # goodbye
If you're not a fan of eval, change the implementation:
$vars = function($str) use ($vars)
{
$r = preg_match_all('~\[\'([a-z-]+)\']~', $str, $keys);
$var = $vars;
foreach($keys[1] as $key)
$var = $var[$key];
return $var;
};
echo $vars("['one']['one-two']"); # goodbye
How about
$vars = array(
'one' => array(
'one-one' => "hello",
'one-two' => "goodbye"
),
'two' => array(
'two-one' => "foo",
'two-two' => "bar"
)
);
function get( $string, $vars )
{
$keys = explode( '][', substr( $string, 1, -1 ) );
foreach( $keys as $key ) {
$vars = $vars[$key];
}
return $vars;
}
echo get( '[two][two-one]', $vars );
For one, you've not got a $var in your get() function. $var was defined outside the function, and PHP scoping rules do not make "higher" vars visible in lower scopes unless explictly made global in the lower scope:
function get($string) {
global $vars;
eval('$x = $vars' . $string);
return $x;
}
get("['two']['two-two']");
might work, but this isn't tested, and using eval is almost always a very bad idea.
Kohana has a nice Config class which alows something like this:
echo Config::get("two.two-two");
You can check it out here: http://kohanaframework.org/3.1/guide/api/Config
Is there a way to change all the numeric keys to "Name" without looping through the array (so a php function)?
[
0 => 'blabla',
1 => 'blabla',
2 => 'blblll',
// etc ...
]
If you have an array of keys that you want to use then use array_combine
Given $keys = array('a', 'b', 'c', ...) and your array, $list, then do this:
$list = array_combine($keys, array_values($list));
List will now be array('a' => 'blabla 1', ...) etc.
You have to use array_values to extract just the values from the array and not the old, numeric, keys.
That's nice and simple looking but array_values makes an entire copy of the array so you could have space issues. All we're doing here is letting php do the looping for us, not eliminate the loop. I'd be tempted to do something more like:
foreach ($list as $k => $v) {
unset ($list[$k]);
$new_key = *some logic here*
$list[$new_key] = $v;
}
I don't think it's all that more efficient than the first code but it provides more control and won't have issues with the length of the arrays.
No, there is not, for starters, it is impossible to have an array with elements sharing the same key
$x =array();
$x['foo'] = 'bar' ;
$x['foo'] = 'baz' ; #replaces 'bar'
Secondarily, if you wish to merely prefix the numbers so that
$x[0] --> $x['foo_0']
That is computationally implausible to do without looping. No php functions presently exist for the task of "key-prefixing", and the closest thing is "extract" which will prefix numeric keys prior to making them variables.
The very simplest way is this:
function rekey( $input , $prefix ) {
$out = array();
foreach( $input as $i => $v ) {
if ( is_numeric( $i ) ) {
$out[$prefix . $i] = $v;
continue;
}
$out[$i] = $v;
}
return $out;
}
Additionally, upon reading XMLWriter usage, I believe you would be writing XML in a bad way.
<section>
<foo_0></foo_0>
<foo_1></foo_1>
<bar></bar>
<foo_2></foo_2>
</section>
Is not good XML.
<section>
<foo></foo>
<foo></foo>
<bar></bar>
<foo></foo>
</section>
Is better XML, because when intrepreted, the names being duplicate don't matter because they're all offset numerically like so:
section => {
0 => [ foo , {} ]
1 => [ foo , {} ]
2 => [ bar , {} ]
3 => [ foo , {} ]
}
This is an example prefixing all the keys with an underscore.
We use array_combine to combine the array keys with the array values, but we first run an array_map function on the array keys, which takes a simple function that adds the prefix.
$prefix = '_';
$arr = array_combine(
array_map(function($v) use ($prefix){
return $prefix.$v;
}, array_keys($arr)),
array_values($arr)
);
See a live example here https://3v4l.org/HABl7
I added this for an answer to another question and seemed relevant. Hopefully might help someone that needs to change the value of the keys in an array. Uses built-in functions for php.
$inputArray = array('app_test' => 'test', 'app_two' => 'two');
/**
* Used to remap keys of an array by removing the prefix passed in
*
* Example:
* $inputArray = array('app_test' => 'test', 'app_two' => 'two');
* $keys = array_keys($inputArray);
* array_walk($keys, 'removePrefix', 'app_');
* $remappedArray = array_combine($keys, $inputArray);
*
* #param $value - key value to replace, should be from array_keys
* #param $omit - unused, needed for prefix call
* #param $prefix - prefix to string replace in keys
*/
function removePrefix(&$value, $omit, $prefix) {
$value = str_replace($prefix, '', $value);
}
// first get all the keys to remap
$keys = array_keys($inputArray);
// perform internal iteration with prefix passed into walk function for dynamic replace of key
array_walk($keys, 'removePrefix', 'app_');
// combine the rewritten keys and overwrite the originals
$remappedArray = array_combine($keys, $inputArray);
// see full output of comparison
var_dump($inputArray);
var_dump($remappedArray);
Output:
array(2) {
'attr_test' =>
string(4) "test"
'attr_two' =>
string(3) "two"
}
array(2) {
'test' =>
string(4) "test"
'two' =>
string(3) "two"
}
I think that he want:
$a = array(1=>'first_name', 2=>'last_name');
$a = array_flip($a);
$a['first_name'] = 3;
$a = array_flip($a);
print_r($a);
The solution to when you're using XMLWriter (native to PHP 5.2.x<) is using $xml->startElement('itemName'); this will replace the arrays key.
change array key name "group" to "children".
<?php
echo json_encode($data);
function array_change_key_name( $orig, $new, &$array ) {
foreach ( $array as $k => $v ) {
$res[ $k === $orig ? $new : $k ] = ( (is_array($v)||is_object($v)) ? array_change_key_name( $orig, $new, $v ) : $v );
}
return $res;
}
echo '<br>=====change "group" to "children"=====<br>';
$new = array_change_key_name("group" ,"children" , $data);
echo json_encode($new);
?>
result:
{"benchmark":[{"idText":"USGCB-Windows-7","title":"USGCB: Guidance for Securing Microsoft Windows 7 Systems for IT Professional","profile":[{"idText":"united_states_government_configuration_baseline_version_1.2.0.0","title":"United States Government Configuration Baseline 1.2.0.0","group":[{"idText":"security_components_overview","title":"Windows 7 Security Components Overview","group":[{"idText":"new_features","title":"New Features in Windows 7"}]},{"idText":"usgcb_security_settings","title":"USGCB Security Settings","group":[{"idText":"account_policies_group","title":"Account Policies group"}]}]}]}]}
=====change "group" to "children"=====
{"benchmark":[{"idText":"USGCB-Windows-7","title":"USGCB: Guidance for Securing Microsoft Windows 7 Systems for IT Professional","profile":[{"idText":"united_states_government_configuration_baseline_version_1.2.0.0","title":"United States Government Configuration Baseline 1.2.0.0","children":[{"idText":"security_components_overview","title":"Windows 7 Security Components Overview","children":[{"idText":"new_features","title":"New Features in Windows 7"}]},{"idText":"usgcb_security_settings","title":"USGCB Security Settings","children":[{"idText":"account_policies_group","title":"Account Policies group"}]}]}]}]}
Use array array_flip in php
$array = array ( [1] => Sell [2] => Buy [3] => Rent [4] => Jobs )
print_r(array_flip($array));
Array ( [Sell] => 1 [Buy] => 2 [Rent] => 3 [Jobs] => 4 )
I did this for an array of objects. Its basically creating new keys in the same array and unsetting the old keys.
public function transform($key, $results)
{
foreach($results as $k=>$result)
{
if( property_exists($result, $key) )
{
$results[$result->$key] = $result;
unset($results[$k]);
}
}
return $results;
}
<?php
$array[$new_key] = $array[$old_key];
unset($array[$old_key]);
?>
To have the same key I think they must be in separate nested arrays.
for ($i = 0; $i < count($array); $i++) {
$newArray[] = ['name' => $array[$i]];
};
Output:
0 => array:1 ["name" => "blabla"]
1 => array:1 ["name" => "blabla"]
2 => array:1 ["name" => "blblll"]
You could create a new array containing that array, so:
<?php
$array = array();
$array['name'] = $oldArray;
?>