Get a single value from a nested associative array - php

For a setup script I write in PHP (for CLI, not web) I use a settings file as well as other other "content" files.
The settings file is built up like a regular ini-file
[header.subheader.moreheaders...]
keyA = value
keyB = value1|value2|...
"header.subheader.moreheaders..." and "keyX" will form a nested associative array with "value" as a string or "value1|value2|..." as a simple array (0-...).
Thanks to this accepted answer, I got so far that I can split the headers into a recursive array recursively. So far, so good.
However, as the content files shall contain references to these variables, I would like to be able to read out single values from that multi-dimensional array with string placeholders like $#R[header.subheader.moreheaders.key] or $#R[header.subheader.moreheaders.key.0] depending on them being a string or an array.
In the script, $#R[header.subheader.moreheaders.key.0] should convert into $SettingsVar[header][subheader][moreheaders][key][0] to return the appropriate value.
Neither the script nor the content files will know what is inside the settings file. The script just knows the general structure and placeholder $#R[...].
This answer appears to know what value will be in order to search for it.
Since I do not fully understand this answer, I am not sure if that would be the right way.
Is there a similar easy way to get the reverse from building that array?

After some contemplation, I found a decent enough solution, which works for me (and hopefully others):
function GetNestedValue($aNestedKeys, $aNestedArray)
{
$vValue = $aNestedArray;
for($i = 0; $i < count($aNestedKeys); $i++)
{
if(array_key_exists($aNestedKeys[$i], $vValue))
{
$vValue = $vValue[$aNestedKeys[$i]];
}
else
{
$vValue = null;
break;
}
}
return $vValue;
}
Depending on what $aNestedKeys contain, it will either return a sub-array from $aNestedArray, a single value from it or null if any of the specified keys were not found.

Related

How can I most efficiently check for the existence of a single value in an array of thousands of values?

Due to a weird set of circumstances, I need to determine if a value exists in a known set, then take an action. Consider:
An included file will look like this:
// Start generated code
$set = array();
$set[] = 'foo';
$set[] = 'bar';
// End generated code
Then another file will look like this:
require('that_last_file.php');
if(in_array($value, $set)) {
// Do thing
}
As noted, the creation of the array will be from generated code -- a process will create a PHP file which will be included above the if statement with require.
How concerned should I be about the size of this mess -- both in bytes, and array values? It could easily get to 5,000 values. How concerned should I be with the overhead of a 5,000-value array? Is there a more efficient way to search for the value, other than using in_array on an array? How painful is including a 5,000-line file via require?
I know there are ultimately better ways of doing this, but my limitations are that the set creation and logic has to be in an included PHP file. There are odd technical restrictions that prevent other options (i.e. -- a database lookup).
A faster way would be:
if (array_flip($set)[$value] !== null) {
// Do thing
}
A 5000 value array really isn't that bad though if it's just strings

PHP retrieve json values without loop through the whole json object

I'm a newbie in the PHP area, so please bear with my question.
Basically I have/will have a pretty big json file, and I need to query the file to get a single entry based on the key provided. An example would be as follow:
{
"key1" : {value1},
"key2" : {value2},
...,
"keyn" : {valuen}
}
I will need to retrieve only one value at any one request, and hope to get a better performance.
The basic way to deal with this sort of handling in PHP from my search is to use json_decode() and then foreach.
However, this approach seems like need to iterate through the whole file based on the order of the key and what the key I am looking for. So if I am looking for keyn, then essentially I have to read from top to bottom of the large file. (Yep, I can use some sort algorithm to get a better result)
But from my understanding, JSON is basically another form of HashMap, so given HashMap can get easily and fast, is there a similar way in PhP to get the best performance out of it?
Well, given the structure you provided you definitely don't need to loop through the entire object.
If you're looking for keyn, you would just do:
$obj = json_decode($input);
echo $obj->keyn;
Maybe I'm missing something obvious. If you want to prevent having to json_decode the entire object, your question makes a bit more sense though... but that's not what you're asking.
From JSON.org
JSON is built on two structures:
A collection of name/value pairs. In various languages, this is realized as an object, >record, struct, dictionary, hash table, keyed list, or associative array.
An ordered list of values. In most languages, this is realized as an array, vector, list, or >sequence.
You can't just interact with json without first using json_decode() to turn it into a usable object. But if you know the keys, after running json_decode() you can interact with it (because it's now an object). for example:
<?php
$string = '{"foo": "bar", "cool": "attr"}';
$result = json_decode($string);
// Result: object(stdClass)#1 (2) { ["foo"]=> string(3) "bar" ["cool"]=> string(4) "attr" }
var_dump($result);
// Prints "bar"
echo $result->foo;
// Prints "attr"
echo $result->cool;
?>
In situations like this, var_dump() and print_r() are your friends.
There really isn't any magical way to find the value without using any kind of loop
I haven't benchmarked this:
This is how I would approach the problem without having to finish the iterating over the whole tree if and when a match is foudn
$key = 'keyn'
$obj = json_decode(file_get_contents('path/to/your/file'), true);
$len = count($obj);
$match = false;
for($ii = 0; $ii < $len; $ii++){
$curr = $obj[$ii];
if($curr == $key) {
$match = $curr;
}
break;
}
In PHP you can use function: file_get_contents to parse JSON file. You have to go through each and every key-value pairs.

Returning by reference

In the PHP documentation it says:
Do not use return-by-reference to increase performance. The engine
will automatically optimize this on its own.
I wish to return a reference to an array (which is a property of my class). How does PHP optimize this, because the array is not an object?
If the array has 1 billion entries, won't I get two arrays with 1 billion entries stored in memory if I don't pass it by reference?
PHP uses copy on write. That means that if you pass the huge array as a function parameter and only read from it (such as a foreach), you won't be writing to it so it doesn't need to make a copy.
$count = count($huge_array); // read the reference at the bottom
for($i = 0; $i < $count $i++) {
$value = 2*$huge_array[$i]/15;
if($value > 3)
$sub_array []= $value;
}
The $subarray which should be smaller (it is a subset of the huge array), will contain only the needed (changed) data.
If you do not intend on changing the values of the original $huge_array it will never get copied so no extra memory is used.
If you intend on changing the original values of the array, you need to pass it by reference.
If you intend on making and returning an altered version of the original array then you do need the extra memory PHP is allocating for you.
If you intend on making and returning an altered smaller subset of the original array then you will create a new empty array into which you will copy some of data from the huge array and should be careful not to overwrite values in the $huge_array, so you'll avoid writing from $huge_array and emphasise on reading from it.
This link explains that PHP was optimised for pass by value use cases.
Copy on write only works if the variable isn't a reference being passed to a function expecting a value, if it is, passing it around triggers a copy.
That makes PHP native functions that expected an argument to be passed by value and received a referenced variable copy the value of the reference.
function foo(&$data) {
for ($i = 0; $i < strlen($data); $i++) {
do_something($data{$i});
}
}
$string = "... looooong string with lots of data .....";
foo(string);
Executing strlen in C would imply iterating over the entire string to count it. In PHP strings have an attached length value. So strlen returns the value read from there (fast).
But if you give it a referenced variable it will have to copy it before reading it's length so it will iterate over the value to copy it into it's argument list, read and return the length (and subsequently release the memory for the freshly copied string).

Create a multi column array using for loop

So as the question states, im trying to create an array using a for loop, this seems as though its a simple question, but i cant find the asnwer on SO or googling. Heres what im doing:
$twelve=array("user","day");
for($i=0; $i<$value; $i++)
{
$total=$anarray[$i][value]; //get a value
$twelve[$i]=($i,$total); //insert values into array
}
this doesn't work, how should i go about getting this to work?
You may end up in a never-ending loop if $total=$anarray[$i][value]; is an increasing value. Regardless of the loop, you'll want to do as the other answerer mentioned, namely:
$twelve[$i] = array($i, $total);
I think it should be $twelve[$i] = array($i, $total);
Also, on this line;
$total=$anarray[$i][value]; //get a value
Unless value is defined as a constant, I think you want to do $anarray[$i][$value];.
PHP might not recognize value as a set variable or a constant, therefore crashes and never sets $twelve to any value.
I have found a solution that does work
in each loop simply do:
$twelve[$i]["user"]=$i;
$twelve[$i]["day"]=$total;
It would be nice if there is a way to do that in one line, but that is working.

PHP: Find common repeating string?

I have this situation in PHP. I have an array that has these keys for example, wires-1, wires-2, wires-3. I need a function or way for my program to read these keys, and find that the common word is wires? How would that be accomplished in PHP? Thanks for your help.
Take a look at how an autocomplete's functionality works, this is similar to your approach.
I'm sure there's plenty of source codes for autocomplete on google
For the string value of every key in your array:
Throw away all non-alpha characters, i.e. leave only letters such that ctype_alpha($remaining_text) should return true.
Keep an array with the found words as keys, and their frequencies as values, as such:
$array = new array();
function found_word($word)
{ global $array;
if(!isset($array[$word])) { $array[$word] = 1; }
else { $array[$word]++; }
}
Only nicer ;)
Sort the array in reverse by using arsort($array);
$array now contains the most found words as its first elements.
you would have to create every possible suffix of every string you have.
create a map for every suffix you found
count the occurence of every suffix in your string array
you can modify the performance with f.ex. limiting the suffix length

Categories