Is there a way to access a PHP multidimensional array (specific index) dynamically?
So for example, say I want to access a value at:
$array[1]['children'][0]['children'][2]['settings']['price']
Can there be a function which returns this value by just getting index (1, 0 and 2 respectively)? and in a way that it works whether there are 3 values (1, 0 and 2) or more.
SO for example , we call function "getArrayValue()" and we can it like so:
getArrayValue('1,0,2')
this should return
$array[1]['children'][0]['children'][2]['country']['city']
or in case of 2 values
getArrayValue('1,0')
should return
$array[1]['children'][0]['country']['city']
so basically, the issue I am facing is needing help with dynamically building the query to get array value...
Or if there is a way to convert a string like $array[1]['children'][0]['country']['city'] and evaluate it to get this value from the array itself?
Another way to explain my problem:
$arrayIndex = "[1]['children'][0]";
$requiredValue = $array[1] . $arrayIndex . ['country']['city'];
//// so $requiredValue should output the same value as the below line would:
$array[1]['children'][0]['children'][2]['country']['city'];
Is there a way to achieve this?
In your case you will need something like this:
<?php
function getArray($i, $j, $k, $array) {
if (isset($array[$i]['children'][$j]['children'][$k]['country']['city']))
{
return $array[$i]['children'][$j]['children'][$k]['country']['city'];
}
}
$array[0]['children'][0]['children'][0]['country']['city'] = "some value";
$array[0]['children'][0]['children'][1]['country']['city'] = "another";
$array[0]['children'][1]['children'][1]['country']['city'] = "another one";
.
.
.
etc
echo getArray(0,0,0, $array) . "\n"; // output -> "some value"
echo getArray(0,0,1, $array) . "\n"; // output -> "another"
echo getArray(0,1,1, $array) . "\n"; // output -> "another one"
Another thing to keep in mind is that you have called the function passing only one parameter. And your multidimensional array needs at least three.
getArrayValue('1,0,2')
You have to take into account that you have called the function passing only one parameter. Even if there were commas. But it's actually a string.
getArrayValue(1,0,2) //not getArrayValue('1,0,2') == string 1,0,2
If you want to pass two values, you would have to put at least one if to control what you want the function to execute in that case. Something like:
function getArray($i, $j, $k, $array) {
if($k==null){
if(isset($array[$i]['children'][$j]['country']['city'])){
return $array[$i]['children'][$j]['country']['city']; //
}
} else {
if(isset($array[%i]['children'][$j]['children'][$k]['country']['city'])){
return $array[$i]['children'][$j]['children'][$k]['country']['city'];
}
}
}
getArray(0,0,null, $array)
getArray(0,0,1, $array)
For the last question you can get by using the eval() function. But I think it's not a very good idea. At least not recommended. Example:
echo ' someString ' . eval( 'echo $var = 15;' );
You can see the documentation: https://www.php.net/manual/es/function.eval.php
edit:
I forgot to mention that you can also use default arguments. Like here.
<?php
$array[0]['children'][0]['children'][0]['country']['city'] = "some value";
$array[0]['children'][0]['children'][1]['country']['city'] = "another";
$array[0]['children'][1]['children'][1]['country']['city'] = "another one";
function getArray($array,$i, $j, $k = null) {
if($k==null){
echo 'getArray called without $k argument';
echo "\n";
}
else{
echo 'getArray called with $k argument';
echo "\n";
}
}
getArray($array,0,0); //here you call the function with only 3 arguments, instead of 4
getArray($array,0,0,1);
In that case $k is optional. If you omit it, the default value will be null. Also you have to take into account that A function may define default values for arguments using syntax similar to assigning a variable. The default is used only when the parameter is not specified; in particular, note that passing null does not assign the default value.
<?php
function makecoffee($type = "cappuccino"){
return "Making a cup of $type.\n";
}
echo makecoffee();
echo makecoffee(null);
echo makecoffee("espresso");
The above example will output:
Making a cup of cappuccino.
Making a cup of .
Making a cup of espresso.
You can read more about that here: https://www.php.net/manual/en/functions.arguments.php
I find #Dac2020's answer to be too inflexible to be helpful to future researchers. In fact, the overly specific/niche requirements in the question does not lend this page to being very helpful for future researchers because the processing logic is tightly coupled to the array structure.
That said, I've tried to craft a function that builds best practices of checking for the existence of keys and D.R.Y. principles in the hope that future researchers will be able to easily modify it for their needs.
Inside the custom function, the first step is to split the csv into an array then interweave the static keys between the dynamic keys as dictated by the asker. In more general use cases, ALL keys would be passed into the function thus eliminating the need to prepare the array of keys.
As correctly mentioned by #MarkusAO in a comment under the question, this question is nearly a duplicate of Convert dot syntax like "this.that.other" to multi-dimensional array in PHP.
Code: (Demo)
function getValue($haystack, $indexes) {
$indices = explode(',', $indexes);
$finalIndex = array_pop($indices);
$keys = [];
foreach ($indices as $keys[]) {
$keys[] = 'children';
}
array_push($keys, $finalIndex, 'country', 'city');
//var_export($keys);
foreach ($keys as $level => $key) {
if (!key_exists($key, $haystack)) {
throw new Exception(
sprintf(
"Path attempt failed for [%s]. No `%s` key found on levelIndex %d",
implode('][', $keys),
$key,
$level
)
);
}
$haystack = $haystack[$key];
}
return $haystack;
}
$test = [
[
'children' => [
[
'children' => [
[
'country' => [
'city' => 'Paris',
]
],
[
'country' => [
'city' => 'Kyiv',
]
]
]
]
]
],
[
'children' => [
[
'country' => [
'city' => 'New York',
]
],
[
'country' => [
'city' => 'Sydney',
]
]
]
]
];
$result = [];
try {
$result['0,0,0'] = getValue($test, '0,0,0');
$result['1,0'] = getValue($test, '1,0');
$result['1,0,0'] = getValue($test, '1,0,0');
} catch (Exception $e) {
echo $e->getMessage() . "\n---\n";
}
var_export($result);
Output:
Path attempt failed for [1][children][0][children][0][country][city]. No `children` key found on levelIndex 3
---
array (
'0,0,0' => 'Paris',
'1,0' => 'New York',
)
Related
I have a variety of arrays that will either contain
story & message
or just
story
How would I check to see if an array contains both story and message? array_key_exists() only looks for that single key in the array.
Is there a way to do this?
Here is a solution that's scalable, even if you want to check for a large number of keys:
<?php
// The values in this arrays contains the names of the indexes (keys)
// that should exist in the data array
$required = array('key1', 'key2', 'key3');
$data = array(
'key1' => 10,
'key2' => 20,
'key3' => 30,
'key4' => 40,
);
if (count(array_intersect_key(array_flip($required), $data)) === count($required)) {
// All required keys exist!
}
If you only have 2 keys to check (like in the original question), it's probably easy enough to just call array_key_exists() twice to check if the keys exists.
if (array_key_exists("story", $arr) && array_key_exists("message", $arr)) {
// Both keys exist.
}
However this obviously doesn't scale up well to many keys. In that situation a custom function would help.
function array_keys_exists(array $keys, array $arr) {
return !array_diff_key(array_flip($keys), $arr);
}
Surprisingly array_keys_exist doesn't exist?! In the interim that leaves some space to figure out a single line expression for this common task. I'm thinking of a shell script or another small program.
Note: each of the following solutions use concise […] array declaration syntax available in php 5.4+
array_diff + array_keys
if (0 === count(array_diff(['story', 'message', '…'], array_keys($source)))) {
// all keys found
} else {
// not all
}
(hat tip to Kim Stacks)
This approach is the most brief I've found. array_diff() returns an array of items present in argument 1 not present in argument2. Therefore an empty array indicates all keys were found. In php 5.5 you could simplify 0 === count(…) to be simply empty(…).
array_reduce + unset
if (0 === count(array_reduce(array_keys($source),
function($in, $key){ unset($in[array_search($key, $in)]); return $in; },
['story', 'message', '…'])))
{
// all keys found
} else {
// not all
}
Harder to read, easy to change. array_reduce() uses a callback to iterate over an array to arrive at a value. By feeding the keys we're interested in the $initial value of $in and then removing keys found in source we can expect to end with 0 elements if all keys were found.
The construction is easy to modify since the keys we're interested in fit nicely on the bottom line.
array_filter & in_array
if (2 === count(array_filter(array_keys($source), function($key) {
return in_array($key, ['story', 'message']); }
)))
{
// all keys found
} else {
// not all
}
Simpler to write than the array_reduce solution but slightly tricker to edit. array_filter is also an iterative callback that allows you to create a filtered array by returning true (copy item to new array) or false (don't copy) in the callback. The gotchya is that you must change 2 to the number of items you expect.
This can be made more durable but verge's on preposterous readability:
$find = ['story', 'message'];
if (count($find) === count(array_filter(array_keys($source), function($key) use ($find) { return in_array($key, $find); })))
{
// all keys found
} else {
// not all
}
One more possible solution:
if (!array_diff(['story', 'message'], array_keys($array))) {
// OK: all the keys are in $array
} else {
// FAIL: some keys are not
}
It seems to me, that the easiest method by far would be this:
$required = array('a','b','c','d');
$values = array(
'a' => '1',
'b' => '2'
);
$missing = array_diff_key(array_flip($required), $values);
Prints:
Array(
[c] => 2
[d] => 3
)
This also allows to check which keys are missing exactly. This might be useful for error handling.
The above solutions are clever, but unnecessarily slow. A simple foreach loop over a few keys is much faster.
function array_keys_exist($keys, $array){
foreach($keys as $key){
if(!array_key_exists($key, $array)) {
return false;
}
}
return true;
}
If you have something like this:
$stuff = array();
$stuff[0] = array('story' => 'A story', 'message' => 'in a bottle');
$stuff[1] = array('story' => 'Foo');
You could simply count():
foreach ($stuff as $value) {
if (count($value) == 2) {
// story and message
} else {
// only story
}
}
This only works if you know for sure that you ONLY have these array keys, and nothing else.
Using array_key_exists() only supports checking one key at a time, so you will need to check both seperately:
foreach ($stuff as $value) {
if (array_key_exists('story', $value) && array_key_exists('message', $value) {
// story and message
} else {
// either one or both keys missing
}
}
array_key_exists() returns true if the key is present in the array, but it is a real function and a lot to type. The language construct isset() will almost do the same, except if the tested value is NULL:
foreach ($stuff as $value) {
if (isset($value['story']) && isset($value['message']) {
// story and message
} else {
// either one or both keys missing
}
}
Additionally isset allows to check multiple variables at once:
foreach ($stuff as $value) {
if (isset($value['story'], $value['message']) {
// story and message
} else {
// either one or both keys missing
}
}
Now, to optimize the test for stuff that is set, you'd better use this "if":
foreach ($stuff as $value) {
if (isset($value['story']) {
if (isset($value['message']) {
// story and message
} else {
// only story
}
} else {
// No story - but message not checked
}
}
What about this:
isset($arr['key1'], $arr['key2'])
only return true if both are not null
if is null, key is not in array
I use something like this quite often
$wantedKeys = ['story', 'message'];
$hasWantedKeys = count(array_intersect(array_keys($source), $wantedKeys)) > 0
or to find the values for the wanted keys
$wantedValues = array_intersect_key($source, array_fill_keys($wantedKeys, 1))
try this
$required=['a','b'];$data=['a'=>1,'b'=>2];
if(count(array_intersect($required,array_keys($data))>0){
//a key or all keys in required exist in data
}else{
//no keys found
}
This is the function I wrote for myself to use within a class.
<?php
/**
* Check the keys of an array against a list of values. Returns true if all values in the list
is not in the array as a key. Returns false otherwise.
*
* #param $array Associative array with keys and values
* #param $mustHaveKeys Array whose values contain the keys that MUST exist in $array
* #param &$missingKeys Array. Pass by reference. An array of the missing keys in $array as string values.
* #return Boolean. Return true only if all the values in $mustHaveKeys appear in $array as keys.
*/
function checkIfKeysExist($array, $mustHaveKeys, &$missingKeys = array()) {
// extract the keys of $array as an array
$keys = array_keys($array);
// ensure the keys we look for are unique
$mustHaveKeys = array_unique($mustHaveKeys);
// $missingKeys = $mustHaveKeys - $keys
// we expect $missingKeys to be empty if all goes well
$missingKeys = array_diff($mustHaveKeys, $keys);
return empty($missingKeys);
}
$arrayHasStoryAsKey = array('story' => 'some value', 'some other key' => 'some other value');
$arrayHasMessageAsKey = array('message' => 'some value', 'some other key' => 'some other value');
$arrayHasStoryMessageAsKey = array('story' => 'some value', 'message' => 'some value','some other key' => 'some other value');
$arrayHasNone = array('xxx' => 'some value', 'some other key' => 'some other value');
$keys = array('story', 'message');
if (checkIfKeysExist($arrayHasStoryAsKey, $keys)) { // return false
echo "arrayHasStoryAsKey has all the keys<br />";
} else {
echo "arrayHasStoryAsKey does NOT have all the keys<br />";
}
if (checkIfKeysExist($arrayHasMessageAsKey, $keys)) { // return false
echo "arrayHasMessageAsKey has all the keys<br />";
} else {
echo "arrayHasMessageAsKey does NOT have all the keys<br />";
}
if (checkIfKeysExist($arrayHasStoryMessageAsKey, $keys)) { // return false
echo "arrayHasStoryMessageAsKey has all the keys<br />";
} else {
echo "arrayHasStoryMessageAsKey does NOT have all the keys<br />";
}
if (checkIfKeysExist($arrayHasNone, $keys)) { // return false
echo "arrayHasNone has all the keys<br />";
} else {
echo "arrayHasNone does NOT have all the keys<br />";
}
I am assuming you need to check for multiple keys ALL EXIST in an array. If you are looking for a match of at least one key, let me know so I can provide another function.
Codepad here http://codepad.viper-7.com/AKVPCH
Hope this helps:
function array_keys_exist($searchForKeys = array(), $inArray = array()) {
$inArrayKeys = array_keys($inArray);
return count(array_intersect($searchForKeys, $inArrayKeys)) == count($searchForKeys);
}
This is old and will probably get buried, but this is my attempt.
I had an issue similar to #Ryan. In some cases, I needed to only check if at least 1 key was in an array, and in some cases, all needed to be present.
So I wrote this function:
/**
* A key check of an array of keys
* #param array $keys_to_check An array of keys to check
* #param array $array_to_check The array to check against
* #param bool $strict Checks that all $keys_to_check are in $array_to_check | Default: false
* #return bool
*/
function array_keys_exist(array $keys_to_check, array $array_to_check, $strict = false) {
// Results to pass back //
$results = false;
// If all keys are expected //
if ($strict) {
// Strict check //
// Keys to check count //
$ktc = count($keys_to_check);
// Array to check count //
$atc = count(array_intersect($keys_to_check, array_keys($array_to_check)));
// Compare all //
if ($ktc === $atc) {
$results = true;
}
} else {
// Loose check - to see if some keys exist //
// Loop through all keys to check //
foreach ($keys_to_check as $ktc) {
// Check if key exists in array to check //
if (array_key_exists($ktc, $array_to_check)) {
$results = true;
// We found at least one, break loop //
break;
}
}
}
return $results;
}
This was a lot easier than having to write multiple || and && blocks.
$colsRequired = ["apple", "orange", "banana", "grapes"];
$data = ["apple"=>"some text", "orange"=>"some text"];
$presentInBoth = array_intersect($colsRequired,array_keys($data));
if( count($presentInBoth) != count($colsRequired))
echo "Missing keys :" . join(",",array_diff($colsRequired,$presentInBoth));
else
echo "All Required cols are present";
Does this not work?
array_key_exists('story', $myarray) && array_key_exists('message', $myarray)
<?php
function check_keys_exists($keys_str = "", $arr = array()){
$return = false;
if($keys_str != "" and !empty($arr)){
$keys = explode(',', $keys_str);
if(!empty($keys)){
foreach($keys as $key){
$return = array_key_exists($key, $arr);
if($return == false){
break;
}
}
}
}
return $return;
}
//run demo
$key = 'a,b,c';
$array = array('a'=>'aaaa','b'=>'ccc','c'=>'eeeee');
var_dump( check_keys_exists($key, $array));
I am not sure, if it is bad idea but I use very simple foreach loop to check multiple array key.
// get post attachment source url
$image = wp_get_attachment_image_src(get_post_thumbnail_id($post_id), 'single-post-thumbnail');
// read exif data
$tech_info = exif_read_data($image[0]);
// set require keys
$keys = array('Make', 'Model');
// run loop to add post metas foreach key
foreach ($keys as $key => $value)
{
if (array_key_exists($value, $tech_info))
{
// add/update post meta
update_post_meta($post_id, MPC_PREFIX . $value, $tech_info[$value]);
}
}
$myArray = array('key1' => '', 'key2' => '');
$keys = array('key1', 'key2', 'key3');
$keyExists = count(array_intersect($keys, array_keys($myArray)));
Will return true, because there are keys from $keys array in $myArray
Something as this could be used
//Say given this array
$array_in_use2 = ['hay' => 'come', 'message' => 'no', 'story' => 'yes'];
//This gives either true or false if story and message is there
count(array_intersect(['story', 'message'], array_keys($array_in_use2))) === 2;
Note the check against 2, if the values you want to search is different you can change.
This solution may not be efficient, but it works!
Updates
In one fat function:
/**
* Like php array_key_exists, this instead search if (one or more) keys exists in the array
* #param array $needles - keys to look for in the array
* #param array $haystack - the <b>Associative</b> array to search
* #param bool $all - [Optional] if false then checks if some keys are found
* #return bool true if the needles are found else false. <br>
* Note: if hastack is multidimentional only the first layer is checked<br>,
* the needles should <b>not be<b> an associative array else it returns false<br>
* The array to search must be associative array too else false may be returned
*/
function array_keys_exists($needles, $haystack, $all = true)
{
$size = count($needles);
if($all) return count(array_intersect($needles, array_keys($haystack))) === $size;
return !empty(array_intersect($needles, array_keys($haystack)));
}
So for example with this:
$array_in_use2 = ['hay' => 'come', 'message' => 'no', 'story' => 'yes'];
//One of them exists --> true
$one_or_more_exists = array_keys_exists(['story', 'message'], $array_in_use2, false);
//all of them exists --> true
$all_exists = array_keys_exists(['story', 'message'], $array_in_use2);
Hope this helps :)
I usually use a function to validate my post and it is an answer for this question too so let me post it.
to call my function I will use the 2 array like this
validatePost(['username', 'password', 'any other field'], $_POST))
then my function will look like this
function validatePost($requiredFields, $post)
{
$validation = [];
foreach($requiredFields as $required => $key)
{
if(!array_key_exists($key, $post))
{
$validation['required'][] = $key;
}
}
return $validation;
}
this will output this
"required": [
"username",
"password",
"any other field"
]
so what this function does is validate and return all the missing fields of the post request.
// sample data
$requiredKeys = ['key1', 'key2', 'key3'];
$arrayToValidate = ['key1' => 1, 'key2' => 2, 'key3' => 3];
function keysExist(array $requiredKeys, array $arrayToValidate) {
if ($requiredKeys === array_keys($arrayToValidate)) {
return true;
}
return false;
}
I wrote this code to find domain names in an array in PHP. My question is how to find the position of the key without using a loop.
I wrote both forms to show my meaning.
<?php
$unique_domains = array( "www.crownworldwide.com","www.acquisition.gov", "www.hemisphere-freight.com",
"www.businessinsider.com","www.oceansidelogistics.com","mixjet.aero","www.airindiaexpress.in", "rlglobal.com",
"www.metroshipping.co.uk","www.flexport.com"
);
$position = array_search("flexport.com",$unique_domains);
echo "position is ". $position . "<br>";
<----------------------------------------->
$position2 = 0 ;
foreach ($unique_domains as $key ) {
$position2++;
if(preg_match('/'.preg_quote("flexport.com").'\b/',$key)){
echo "position is ".$position2 ;
}
}
?>
On the first method I was not able to find the position as it has www. at the beginning. On the second method I can find the position but I do not want to use a loop in my live platform. What are the alternative to find the domain names inside an array?
Update:
Also the result must be domain specific and all subdomains must be accepted.
For example:
flexport.com :
flexport.co - is wrong
app.flexport.co is correct
Another way is to use preg_match() and a simple foreach. This method avoid the iteration of all items of the array and stops when a match is found.
/**
* Returns the index of the first match or false if not found.
*/
function arraySearch(array $array, string $search): int|false
{
foreach ($array as $key => $value) {
if (preg_match('~' . $search . '$~',$value)) {
return $key;
}
}
return false;
}
$unique_domains = [
'www.crownworldwide.com',
'www.acquisition.gov',
'www.hemisphere-freight.com',
'www.businessinsider.com',
'www.oceansidelogistics.com',
'mixjet.aero',
'www.airindiaexpress.in',
'rlglobal.com',
'www.metroshipping.co.uk',
'www.flexport.com'
];
var_dump(arraySearch($unique_domains, 'flexport.co')); // bool(false)
var_dump(arraySearch($unique_domains, 'flexport.com')); // int(9)
live demo PHP 8.0
live demo PHP 7.4
$unique_domains = [
'www.crownworldwide.com',
'www.acquisition.gov',
'www.hemisphere-freight.com',
'www.businessinsider.com',
'www.oceansidelogistics.com',
'mixjet.aero',
'www.airindiaexpress.in',
'rlglobal.com',
'www.metroshipping.co.uk',
'www.flexport.com'
];
$position = array_key_first(array_filter($unique_domains, fn($val) => str_contains($val, 'flexport.com')));
echo 'position is ' . $position;
$input = preg_quote('flexport.com', '~'); // don't forget to quote input string!
$data = array("www.crownworldwide.com","www.acquisition.gov", "www.hemisphere-freight.com",
"www.businessinsider.com","www.oceansidelogistics.com","mixjet.aero","www.airindiaexpress.in", "rlglobal.com",
"www.metroshipping.co.uk","www.flexport.com");
$result = preg_grep('~' . $input . '~', $data);
var_dump($result); // array(1) { [9]=> string(16) "www.flexport.com" }
array_keys($result); // [9]
Update 2.0
I think we should take a simple and pragmatic approach here. The goal is to only get the index of an array if the search domain matches. Regardless of whether with www. or without.
A function that accepts a search string. Remove the www. in the search string as well as the values of the array. This way you compare domain with domain. and you only get unique results. Then return the key. that's it!
<?php
function position($search) {
$unique_domains = [
'www.crownworldwide.com',
'www.acquisition.gov',
'www.hemisphere-freight.com',
'www.businessinsider.com',
'www.oceansidelogistics.com',
'mixjet.aero',
'www.airindiaexpress.in',
'rlglobal.com',
'www.metroshipping.co.uk',
'www.flexport.com'
];
foreach($unique_domains as $k => $v)
{
$plain_1 = str_replace("www.","",$v);
$plain_2 = str_replace("www.","",$search);
if($plain_1 == $plain_2) {
return $k;
}
}
return false;
}
print_r('flexport.com => ' .position('flexport.com')); // 9
echo '<br/>';
print_r('www.flexport.com => ' . position('www.flexport.com')); // 9
echo '<br/>';
print_r('om' . position('om')); // 0
**working example (updated 2.0) **
https://3v4l.org/B4TAu#v8.1.2
I have the following array:
$people['men'] = [
'first_name' => 'John',
'last_name' => 'Doe'
];
And I have the following flat array:
$name = ['men', 'first_name'];
Now I want to create a function that "reads" the flat array and gets the value from the multidimensional array, based on the sequence of the elements of the flat array.
function read($multidimensionalArray,$flatArray){
// do stuff here
}
echo read($people,$name); // must print 'John'
Is this even possible to achieve? And which way is the way to go with it? I'm really breaking my head over this. I have no clue at all how to start.
Thanks in advance.
This should to the trick:
<?php
$people['men'] = [
'first_name' => 'John',
'last_name' => 'Doe'
];
$name = ['men', 'first_name'];
echo read($people,$name);
function read($multidimensionalArray,$flatArray){
$cur = $multidimensionalArray;
foreach($flatArray as $key)
{
$cur = $cur[$key];
}
return $cur;
}
Link: https://3v4l.org/96EnQ
Be sure to put some error checking in there (isset and the likes)
You can use a recursive function to do this.
function read(&$array, $path) {
// return null if one of the keys in the path is not present
if (!isset($array[$key = array_shift($path)])) return null;
// call recursively until you reach the end of the path, then return the value
return $path ? read($array[$key], $path) : $array[$key];
}
echo read($people, $name);
You could also use array_reduce
$val = array_reduce($name, function($carry, $item) {
return $carry[$item];
}, $people);
looks like you just want:
echo $multidimensionalArray[$flatArray[0]][$flatArray[1]];
I want to delete a whole array within an array selected by a specific value.
This is the code I got so far.
Since I'm unsetting the array with all the subarrays and then inserting back the subarrays what could (I think) lead to huge performance problems with larger or more arrays.
So my question is there a way to optimise the code below or just remove the one array and leave the rest untouched?
Thanks :)
<?php
$currentValue = '#6';
$otherValue = [ "ID" => '2', "valueID" => '#6' ];
$otherValue2 = [ "ID" => '3', "valueID" => '#7' ];
$otherValue3 = [ "ID" => '4', "valueID" => '#8' ];
$valueArray = [ $otherValue, $otherValue2, $otherValue3 ];
echo 'current value: '.$currentValue;
echo '<br><br>';
print_r($valueArray);
echo '<br><br>';
foreach( $valueArray as $key => $value ) {
echo 'Value: ';
print_r($value);
if(($key = array_search($currentValue, $value)) !== false) {
echo ' - true, '.$currentValue.' is in $value<br>';
unset($value);
unset($valueArray);
if( isset($value) ) {
print_r($value);
echo '<br>';
} else {
echo '$value was deleted<br><br>';
}
} else {
echo ' - false<br>';
$valueArray[] = $value;
}
}
echo '<br>';
print_r($valueArray);
?>
Your code will return the wrong result in many cases, for instance when the searched for value is not found at all, or in the last sub-array. This is because of the following lines:
unset($valueArray);
and
$valueArray[] = $value;
That first statement destroys any previous result made with the second. Or if the first is never executed, the second just adds to the original array, making it twice its original size.
Instead you could use array_filter:
$valueArray = array_filter($valueArray, function ($value) use ($currentValue) {
return array_search($currentValue, $value) === false;
});
See it run on eval.in.
As #shudder noted in comments, it is strange that you want to search the value in all the keys. From the example you have given it looks like you are expecting to find it under the valueID key.
In that case you can optimise your code and do:
$valueArray = array_filter($valueArray, function ($value) use ($currentValue) {
return $value['valueID'] !== $currentValue;
});
See it run on eval.in.
I want to pass one argument to a function, rather than multiple arguments, that tend to grow unexpectedly. So I figure an array will get the job done. Here's what I've drafted so far...
<?php
function fun_stuff($var){
// I want to parse the array in the function, and use
}
$my = array();
$my['recordID'] = 5;
$my['name'] = 'John Smith';
$my['email'] = 'john#someemail.com';
echo fun_stuff($my);
?>
I haven't quite grasped the concept of parsing an array. And this is a good way for me to learn. I generally pass the same variables, but on occasion a record does not have an email address, so I do need to make a condition for missing keys.
Am I doing this right so far? Can I pass an array as an argument to a function?
And if so, how do I parse and search for existing keys?
Hopefully this isn't too far off topic...but you sounded like you were just trying to avoid multiple parameters when some can be NULL. So, I would recommend that you use an object instead of an array for clarity...that way, there is no confusion as to what properties should exist. If you're using PHP 5, you can also strongly type the parameter so nothing else can get in. So:
class Record {
public $Id;
public $Name;
public $Email
}
function fun_stuff( Record $record ) {
// you will now have better intellisense if you use an IDE
// and other develoers will be able to see intended parameters
// clearly, while an array would require them to know what's
// intended to be there.
if( !empty($record->Email) ) {
// do whatever.
}
}
Yes you are on the right track. The approach I take is put required paramters as the first parameters and all optional parameters in the last argument which is an array.
For example:
function fun_stuff($required1, $required2, $var = array()) {
// parse optional arguments
$recordId = (key_exists('recordID', $var) ? $var['recordId'] : 'default value');
$name = (key_exists('name', $var) ? $var['name'] : 'default value');
$email = (key_exists('email', $var) ? $var['email'] : 'default value');
}
Then you can call your function like so:
fun_stuff('val 1', 'val 2', array(
'recordId' => 1,
'name' => 'John',
'email' => 'john#stackoverflow.com'
));
This is a bad design practice, but that's not the question here. You can "parse" array's like so...
if( array_key_exists( 'email', $var ))
{
// use email field
}
If you need to, you can loop through all elements like so...
foreach( $var as $key => $value )
{
echo '$var[\''.$key.'\'] = '.$value;
}
I'm not recommend you to use array for this.
You can define optional arguments with default values:
//$name and $email are optional here
function fun($record_id, $name='', $email='')
{
if (empty($name)) print '$name is empty';
}
//Usage:
fun(5, 'Robert');
fun(5);
fun(5, 'Robert', 'robert#gmail');
fun(3,'','robert#gmail');
If you will use array, IDE will not be able to show autocomplete suggestions, it means more typos, and you have to remember all keys of this array forever or look at code of the function each time.
I'm not really sure what you want to achieve, but I suspect something like this:
$aPersons = array();
$aPersons[] = array('name' => 'name1', 'age' => 1);
$aPersons[] = array('name' => 'name2', 'age' => 2);
array_map('parsePerson', $aPersons);
function parsePerson($aPerson) {
echo $aPerson['name'];
echo $aPerson['age'];
}
The problem with your current array is that it only has one dimension.
You can simple do echo $my['name'];. There are easier ways to parse arrays though.
foreach($aPersons as $aPerson) {
echo $aPerson['name'];
echo $aPerson['age'];
}
$iLength = sizeof($aPersons);
for($i = 0; $i <= $iLength; $i++) {
echo $aPersons[$i]['name'];
echo $aPersons[$i]['age'];
}
To parse and view, there is the signficant print_r function which gives out the array details.
When calling a function you need the return syntax at the end that will parse out anything you call in the return.
You obviously can pass array to the function. Inside it read the variable as you were assigning values before it. If you assign:
$my['key'] = 'value';
In you function use:
echo $var['key'];
Why you don't use a foreach to walk in array?
function fun_stuff($var){
foreach($var as $key => $item){
echo '[', $key, "] => ", $item, "\n";
}
}
$my = array();
$my['recordID'] = 5;
$my['name'] = 'John Smith';
$my['email'] = 'john#someemail.com';
fun_stuff($my);
Yes, this is correct (though your question is a bit broad). You're already referencing the array values via indexes when you set up the $my variable. You can do the same thing within your function (with the $var variable).
I recommend taking a look at all of PHP's built-in array functions: http://php.net/manual/en/ref.array.php
Try this:
function fun_stuff($var){
// I want to parse the array in the function, and use
$fun_string = "";
if( is_array( $var ) {
if( array_key_exists( "name", $var ) )
$fun_string .= "For " . $var["name"];
else $fun_string .= "A nameless one ";
if( array_key_exists( "email", $var ) )
$fun_string .= " (email: " . $var["email"] . ")";
else $fun_string .= " without a known e-mail address";
if( array_key_exists( "recordID", $var ) )
$fun_string .= " has record ID of " . $var["recordID"];
else $fun_string .= " has no record ID set";
$fun_string .= "\n";
}
return $fun_string;
}
Yes You can! Just pass the array and inside the function just use a foreach loop to parse it!
function myFunction($array)
{
foreach($array as $value)
{
echo $value;
}
}
or If you want to have full control over the pair key/value:
function myFunction($array)
{
foreach($array as $key=>$value)
{
echo "key:".$array[$key]."value:".$values;
}
}