I have the following object in PHP 7:
(int) 0 => object() {
'master' => null
},
(int) 1 => object() {
'master' => true
},
(int) 2 => object() {
'master' => null
},
What is the most efficient way to check whether master is true in any key of that object?
I could loop through the object and then set a variable, e.g.
$master = 0;
foreach ($obj as $key => $value) {
if ($value->master) {
$master++;
}
}
if ($master !== 0) {
}
But this seems inefficient.
The object itself has other data in each node, this is a simplified example.
What I'm trying to write, in as few lines as possible is, does any part of this object have master == true? Or, looking at it the other way round, are all my master nodes set to null on this object? A return of true or false would probably suffice as the output, although a count would also be ok.
Assuming that you don't want to loop through the array, and the key of the "master" array is always "master", then this one-liner should do it:
$masterCount = count(array_filter(array_column($masterArray,'master')));
array_column is used to fetch all of the values of the "master" column, array_filter without a closure will automatically filter out empty values (false, null, 0) and count of the new array will get you the amount of true values.
if ($value->master && $value->master !== null) {
$master++;
}
Have a look to this table :
http://php.net/manual/en/types.comparisons.php
Use triple equal
if ($value->master === TRUE) {
// your code here
}
Related
I am using the Laravel framework, I have an array of dates where I want to check if there are two same dates exist. The array is this
array:5 [▼
0 => "2020-04-11"
1 => "2020-04-11"
2 => "2020-04-12"
3 => "2020-04-13"
4 => "2020-04-21"
]
I have written the following function to check, it works but I curious if there is any better way to achieve this because I have to extend it soon so there will be more nested loops.
private function validateFlyingDatesAreOverlapping($flyingDates)
{
foreach ($flyingDates as $key => $datePick) {
$datePickInstance = Carbon::parse($datePick)->startOfDay();
foreach ($flyingDates as $index => $dateCompare) {
$dateCompare = Carbon::parse($dateCompare)->startOfDay();
if ($key != $index) {
$result = $datePickInstance->eq($dateCompare);
if ($result) {
return true;
}
}
}
}
return false;
}
You can use collection unique and count method:
$is_same_exists = !(collect($data)->count() == collect($data)->unique()->count());
If you just need to know if duplicates is exists without getting the values (your function returns boolean, so looks like this is what you need), then you can just compare the count of items in the initial array with count of unique items in array, like this:
if (count(array_unique($array)) != count($array)) {
//duplicates is exists
}
I am trying to make a simple class that I can use to check if a value exists within an array. There is a session that contains multiple tool values. I am trying to pass the toolID to this function as well as a key and see if that value exists.
Session Data:
Array
(
[keyring] => Array
(
[tool] => Array
(
[toolID] => 1859
[keys] => Array
(
[0] => 49
[1] => 96
)
)
)
)
class Keyring
{
public function checkKey($key, $toolID){
$keyring = $_SESSION['keyring'];
if(isset($keyring)){
foreach($keyring['tool'] as $k => $v) {
if($k == 'toolID' && $v == $toolID){
if (in_array($key, $k->keys)){
return true;
}
}
}
}
return false;
}
}
$keyring = new Keyring();
print_r($keyring->checkKey(49, 1859));
In this example, I am trying to see if key 49 exists in the session for tool 1859.
I am getting the following error : Warning: in_array() expects parameter 2 to be array, null given in.
Is there a better approach for this? All I am looking for is a true/false as to whether that key exists in the keys array for the specified tool.
For my code to work for you may need to change your array a bit or change the code a bit, but rather then looping through a bunch of keys trying to find the right one we are just looking for the keys in the array if they are not set, then return false, or if we find keyring - tools - $tool_id - key_{$key_id} we are just going to return that value, if key_49 = false the function returns false. This should be a tad bit quicker to run on the server for you.
function has_keyring($tool_id, $key_id)
{
//Just to keep the code tidy let's store the tools key in $tool variable
$tool = $_SESSION['keyring']['tools'];
if(isset($tool[$tool_id]) && isset($tool[$tool_id]["key_{$key_id}"]))
return $tool[$tool_id]["key_{$key_id}"];
return false;
}
I am trying to create php array (associative) declaration for non-empty key-value pairs only, which I am getting from $_POST. Any guesses, how to do this ?
$my_array = [
"k1"=>"$val1",
"k2"=>"$val2",
"k3"=>"$val3",
"k4"=>"$val4"
];
But, if $val4 & $val3 are empty / NULL / does'nt exist, then :
$my_array = [
"k1"=>"$val1",
"k2"=>"$val2"
];
Thanks
As others mentioned you can use array filter,
if you dont want values of 0 being treated as empty you can do something like this
$post = array_filter( $_POST, function( $item ){ return strlen( $item ); });
Array filter will treat 0, '', false, null and I think '0' and possibly some others all as empty. You can use a callback, such as my example. When the call back returns false 0 the item is removed when it returns true ( or > 0 ) it is retained. So strlen will return a value equal to the length of the string and any strings of 0 length are then removed.
-note- this should be fine on $_POST because it's generally not going to have any nested arrays, but if there are nested arrays then strlen will obviously not work on an array ( being this $item = array() in the callback ).
$_POST is already an associative array. For example, with a form, the key is the element 'name' and the value is the user's input. Empty inputs will still generate a key/value pair but you can easily filter these with array_filter()
EDIT:
Here is an example implementation:
array_filter($array, function(x) {
if is_null(x) return false;
else return true;
});
You can write a function to check null or empty values like this:
<?php
function transform(&$data) {
foreach(array_keys($data) as $key) {
if( is_null($data[$key])
|| empty($data[$key])
) {
unset($data[$key]);
}
}
}
// usage
$data = [
"example1" => 5,
"example2" => "some text",
"example3" => null,
"example4" => [],
];
transform($data);
print_r($data);
?>
Example output of print_r() :
Array
(
[example1] => 5
[example2] => some text
)
Taking a dictionary as an example, let's say I've got the following array to catalog the pronunciations of a given word:
$pronunciation["text"] = array("alpha", "beta", "gamma", "delta", "epsilon");
$pronunciation["definition"] = array(1, 2, NULL, NULL, 1);
text contains the pronunciation that will be displayed to the user, while definition contains the ID for the definition in the list where that pronunciation applies. If definition is NULL, it's not associated with any particular definition, and should be displayed elsewhere in the entry.
Now, if I try to do something like the following:
$key = array_search(1, $pronunciation["definition"]);
All I'll get is 0, since that's the first key in definition that contains the value. Likewise, substituting NULL returns 3, however both of these actually have another related key that I'm trying to fetch.
Is there a way to get it to return all related keys without having to resort to brute force methods such as a for loop?
Try this one:
array_keys($pronunciation["definition"],1)
I'm afraid there is not a function that do that as you want. Edit: Nope, there is! See Jauzsika answer.You have to use a foreach or a for loop.
function array_search_all($needle, $haystack) {
$keys = array();
foreach ($haystack as $k => $v) if ($v === $needle) $keys[] = $k;
return $keys;
}
Call:
$keys = array_search_all(1, $pronunciation["definition"]);
I don't know wheter it's faster or not, but I think if there're a set of data which you have to search in, it's better to set up an array, where the data is the key.
$data["alpha"] = 1
$data["beta"] = 1
//...
All your foreach should be modified from
foreach ($data as $item) {
to
foreach ($data as $item => $value) {
Restructure your arrays into a single array keyed on the text and using the definition as the value:
$pronunciation = array("alpha" => 1,
"beta" => 2,
"gamma" => NULL,
"delta" => NULL,
"epsilon" => 1);
Then use array_filter() to build a subset of the values you need
$searchVal = 1;
$subset = array_filter($pronunciation,
create_function('$value', 'return $value == '.$searchVal.';')
);
var_dump($subset);
I am using Cakephp and try to customize the paginator result with some checkboxes .I was pass parameters in URL like this
"http://localhost/myproject2/browses/index/page:2/b.sonic:1/b.hayate:7/b.nouvo:2/b.others:-1/b.all:-2"
and cakephp translate URL to be the array like this
Array
(
[page] => 2
[b.sonic] => 1
[b.hayate] => 7
[b.nouvo] => 2
[b.others] => -1
[b.all] => -2
)
other time when I pass params without checking any checkbox.
"http://localhost/myproject2/browses/index/page:2"
and cakephp translate URL to be the array like this
Array
(
[page] => 2
)
how to simple check if [b.????] is available or not? I can't use !empty() function because array[page] is getting on the way.
If you want to check if a specific item is present, you can use either :
isset()
or array_key_exists()
But if you want to check if there is at least one item which has a key that starts with b. you will not have much choice : you'll have to loop over the array, testing each key.
A possible solution could look like this :
$array = array(
'page' => 'plop',
'b.test' => 150,
'b.glop' => 'huhu',
);
$found_item_b = false;
foreach (array_keys($array) as $key) {
if (strpos($key, 'b.') === 0) {
$found_item_b = true;
break;
}
}
if ($found_item_b) {
echo "there is at least one b.";
}
Another (possibly more fun, but not necessarily more efficient ^^ ) way would be to get the array of items which have a key that starts with b. and use count() on that array :
$array_b = array_filter(array_keys($array), function ($key) {
if (strpos($key, 'b.') === 0) {
return true;
}
return false;
});
echo count($array_b);
If page is always going to be there, you could simply do a count.
if (count($params) == 1) {
echo "There's stuff other than page!";
}
You could be more specific and check page is there and the count is one.
I think this is what you are looking for, the isset function so you would use it like...
if(isset(Array[b.sonic]))
{
//Code here
}