This question already has answers here:
How to search by key=>value in a multidimensional array in PHP
(17 answers)
Closed 9 years ago.
What's the most efficient way to search an array element's sub arrays to check the value of a specific key? For example, given the following array, where I want to check both subarrays "msg" value, and if either is populated, return a boolean result:
[TGMN02] => Array
(
[2] => Array
(
[id] => 93143
[msg] =>
)
[3] => Array
(
[id] => 24876
[msg] =>
)
)
What I have at the moment is simply looping through and checking, which feels quite clunky.
I don't know about "most" efficient but this won't necessarily have to iterate through the whole array as it breaks the loop on the first value found, so technically more efficient.
function hasMsg($a){
foreach($a as $b)
if(!empty($b['msg'])) return true;
return false;
}
Okay... since some meager comments weren't accompanied by alternative suggestions - you could try using some PHP>5.3 - I really can't see how it would be any more efficient though - it must still loop through the array at some level (but I'm not 100% sure on the inner workings of the PHP interpreter - perhaps there is some internal magic that could speed things up), so this is probably purely aesthetic:
$hasMsg = !!(count(array_filter($a,function($b){ return !empty($b['msg']); })));
... if anything less efficient. There's nothing wrong with "looping" through an array - it's a tried and tested language construct that's been around since the dawn of digital time (almost).
First write some custom func and then try to use it with array_walk_recursive(array &$input , callable $funcname [, mixed $userdata = NULL ]) function. Php manual.
Related
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Create array printed with print_r
Duplicate of How create an array from the output of an array printed with print_r?
which also has a nice code example to solve this
I need to reverse an error log which has as output print_r($data,true).
Example data would look like:
Array
(
[subject] => this is the subject
[body] => <p>Dear user,</p><p>this is the body of the email</p>
[from_id] => 0
[from_email] => admin#karakas.org
[to] => Array
(
[0] => Array
(
[id] => 0
[email] => 64909
)
)
[send_to_inbox] => 1
)
In the PHP manual there's a print_r_reverse() function in comments :
http://php.net/manual/en/function.print-r.php
However var_export() can be an alternative if your logs are generated using var_export(). This way, you only need eval() to retrieve the exported array.
The output of print_r() is not designed to parsed; it's designed to be read by a developer for debugging purposes. You should not be trying to parse it.
If you really must parse a PHP data dump of this nature, the var_export() function is intended for this kind of thing. However, I wouldn't recommend parsing this either -- it's still unlikely to be the best solution for you.
If your intention is to store a string representation of an array structure, and then parse it later, you would be better off using either the serialize()/unserialize() functions, or the json_encode()/json_decode() functions.
Both of these will give you a much more reliable and easily parseable data dump format. Of the two, I'd recommend json_encode() every time, as not only is it easy to work with, it's also supported by other languages, easy to read manually, and compact.
In short, don't parse print_r() output; use json_encode()/json_decode() instead.
http://uk1.php.net/manual/en/function.json-encode.php
My first question post here, although I'm a long time user. My PHP skills aren't advanced. I'm using PHP7 BTW.
I've found similar questions to this one, but not with the tier element, and so none of the answers I've tried so far have worked. It's probably obvious to a more experienced PHP programmer.
I've got some data in the json format, and decoded it into the following array:
Array (
[soc] => 3421
[series] => Array (
[0] => Array ( [year] => 2013 [estpay] => 620 )
[1] => Array ( [year] => 2015 [estpay] => 580 )
)
)
The data source varies, and so some times there are more years data available and sometimes less. It will also change over time as new data is added.
I want to sort the array so that the most recent year is always first. As I mentioned earlier, I've tried a few of the solutions that have been posted on here for multidimensional arrays, but the data I'm using has the multidimensional array in a lower tier of the array, and so I haven't been able to work out how to change the example code for multidimensional arrays to work around this.
As I mentioned, I'm no PHP expert, so please make no assumptions on my skill level in any replies. Thanks for your help!
Assuming you're using PHP7, and as you said you want to order by year descending, then for each array that you want to sort, try the below:
usort($array, function ($a, $b) {
return $b['year'] <=> $a['year'];
});
I want to check, if array A contains all the items from array B (may contain others, but must contain all), when both arrays are multidimensional, i.e. can contains different variable types.
I've seen a lot (particularly this, this, this, this, this and this, also this, this and this as well). I've read PHP doc. Everything, that I checked, fails with "Array to string conversion" notice. Especially wen using array_intersect() or array_diff().
I'm using strict error checking, so notices actually holds further execution of entire script and are something, I don't generally like and want to avoid. Is it possible in this case?
My array A is:
Array
(
[0] => content/manage/index
[Content] => Array
(
[title] =>
[type] => 5
[category] =>
[recommended] =>
[featured] =>
[status] =>
[views] =>
[last_access_date] =>
[creation_date] =>
[modification_date] =>
[availability_date] =>
[author_id] =>
)
)
My array B is:
Array
(
[0] => /content/manage/index
[Content] => Array
(
[type] => 1
)
)
So, is there any way I can if I can use array_intersect on multidimensional arrays containing different variable types without getting notice?
My problem (and question) came out of misunderstanding, what "Array to string conversion" notice really means. In my case, it was trying to tell me, that I'm trying to walk multidimensional array with functions designed to be used on single dimension array.
Understanding that led me to a solution within few seconds. There are many of them here, on SO, but the one given by deceze here looked the best for me. So I adopted it into the form of such function:
function recursiveArrayIntersect($array1, $array2)
{
$array1 = array_intersect_key($array1, $array2);
foreach($array1 as $key=>&$value)
{
if(is_array($value)) $value = recursiveArrayIntersect($value, $array2[$key]);
}
return $array1;
}
I adopted it to my project and my way of coding, but all the credits still goes to deceze (his answer here)!
Now I can find an intersection of virtually any array, no matter what kind of variable types it contain and no matter of, how deep it is (how many subarrays it contains).
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Create array printed with print_r
Duplicate of How create an array from the output of an array printed with print_r?
which also has a nice code example to solve this
I need to reverse an error log which has as output print_r($data,true).
Example data would look like:
Array
(
[subject] => this is the subject
[body] => <p>Dear user,</p><p>this is the body of the email</p>
[from_id] => 0
[from_email] => admin#karakas.org
[to] => Array
(
[0] => Array
(
[id] => 0
[email] => 64909
)
)
[send_to_inbox] => 1
)
In the PHP manual there's a print_r_reverse() function in comments :
http://php.net/manual/en/function.print-r.php
However var_export() can be an alternative if your logs are generated using var_export(). This way, you only need eval() to retrieve the exported array.
The output of print_r() is not designed to parsed; it's designed to be read by a developer for debugging purposes. You should not be trying to parse it.
If you really must parse a PHP data dump of this nature, the var_export() function is intended for this kind of thing. However, I wouldn't recommend parsing this either -- it's still unlikely to be the best solution for you.
If your intention is to store a string representation of an array structure, and then parse it later, you would be better off using either the serialize()/unserialize() functions, or the json_encode()/json_decode() functions.
Both of these will give you a much more reliable and easily parseable data dump format. Of the two, I'd recommend json_encode() every time, as not only is it easy to work with, it's also supported by other languages, easy to read manually, and compact.
In short, don't parse print_r() output; use json_encode()/json_decode() instead.
http://uk1.php.net/manual/en/function.json-encode.php
I have a very strange array sorting related problem in PHP that is driving me completely crazy. I have googled for hours, and still NOTHING indicates that other people have this problem, or that this should happen to begin with, so a solution to this mystery would be GREATLY appreciated!
To describe the problem/question in as few words as possible: When sorting an array based on values inside a multiple levels deeply nested array, using a foreach loop, the resulting array sort order reverts as soon as execution leaves the loop, even though it works fine inside the loop. Why is this, and how do I work around it?
Here is sample code for my problem, which should hopefully be a little more clear than the sentence above:
$top_level_array = array('key_1' => array('sub_array' => array('sub_sub_array_1' => array(1),
'sub_sub_array_2' => array(3),
'sub_sub_array_3' => array(2)
)
)
);
function mycmp($arr_1, $arr_2)
{
if ($arr_1[0] == $arr_2[0])
{
return 0;
}
return ($arr_1[0] < $arr_2[0]) ? -1 : 1;
}
foreach($top_level_array as $current_top_level_member)
{
//This loop will only have one iteration, but never mind that...
print("Inside loop before sort operation:\n\n");
print_r($current_top_level_member['sub_array']);
uasort($current_top_level_member['sub_array'], 'mycmp');
print("\nInside loop after sort operation:\n\n");
print_r($current_top_level_member['sub_array']);
}
print("\nOutside of loop (i.e. after all sort operations finished):\n\n");
print_r($top_level_array);
The output of this is as follows:
Inside loop before sort operation:
Array
(
[sub_sub_array_1] => Array
(
[0] => 1
)
[sub_sub_array_2] => Array
(
[0] => 3
)
[sub_sub_array_3] => Array
(
[0] => 2
)
)
Inside loop after sort operation:
Array
(
[sub_sub_array_1] => Array
(
[0] => 1
)
[sub_sub_array_3] => Array
(
[0] => 2
)
[sub_sub_array_2] => Array
(
[0] => 3
)
)
Outside of loop (i.e. after all sort operations finished):
Array
(
[key_1] => Array
(
[sub_array] => Array
(
[sub_sub_array_1] => Array
(
[0] => 1
)
[sub_sub_array_2] => Array
(
[0] => 3
)
[sub_sub_array_3] => Array
(
[0] => 2
)
)
)
)
As you can see, the sort order is "wrong" (i.e. not ordered by the desired value in the innermost array) before the sort operation inside the loop (as expected), then is becomes "correct" after the sort operation inside the loop (as expected).
So far so good.
But THEN, once we're outside the loop again, all of a sudden the order has reverted to its original state, as if the sort loop didn't execute at all?!?
How come this happens, and how will I ever be able to sort this array in the desired way then?
I was under the impression that neither foreach loops nor the uasort() function operated on separate instances of the items in question (but rather on references, i.e. in place), but the result above seems to indicate otherwise? And if so, how will I ever be able to perform the desired sort operation?
(and WHY doesn't anyone else than me on the entire internet seem to have this problem?)
PS.
Never mind the reason behind the design of the strange array to be sorted in this example, it is of course only a simplified PoC of a real problem in much more complex code.
Your problem is a misunderstanding of how PHP provides your "value" in the foreach construct.
foreach($top_level_array as $current_top_level_member)
The variable $current_top_level_member is a copy of the value in the array, not a reference to inside the $top_level_array. Therefore all your work happens on the copy and is discarded after the loop completes. (Actually it is in the $current_top_level_member variable, but $top_level_array never sees the changes.)
You want a reference instead:
foreach($top_level_array as $key => $value)
{
$current_top_level_member =& $top_level_array[$key];
EDIT:
You can also use the foreach by reference notation (hat tip to air4x) to avoid the extra assignment. Note that if you are working with an array of Objects, they are already passed by reference.
foreach($top_level_array as &$current_top_level_member)
To answer you question as to why PHP defaults to a copy instead of a reference, it's simply because of the rules of the language. Scalar values and arrays are assigned by value, unless the & prefix is used, and objects are always assigned by reference (as of PHP 5). And that is likely due to a general consensus that it's generally better to work with copies of everything expect objects. BUT--it is not slow like you might expect. PHP uses a lazy copy called copy on write, where it is really a read-only reference. On the first write, the copy is made.
PHP uses a lazy-copy mechanism (also called copy-on-write) that does
not actually create a copy of a variable until it is modified.
Source: http://www.thedeveloperday.com/php-lazy-copy/
You can add & before $current_top_level_member and use it as reference to the variable in the original array. Then you would be making changes to the original array.
foreach ($top_level_array as &$current_top_level_member) {