PHP OOP Multidimensional Array Search Issue - php

I have a function
function GetArrKey( $findArr, $key_arr, $depth=0 )
{
if( count($key_arr) <= $depth || !array_key_exists($key_arr[$depth], $findArr) )
return NULL;
else if( count($key_arr) == $depth+1 )
return $findArr[$key_arr[$depth]];
return self::GetArrKey( $findArr[$key_arr[$depth]], $key_arr, $depth+1 );
}
That searches an array and returns the part of the array that matches what I need.
The only problem is it seems to be returning the exact same value. For example, I have this function in a foreach loop
foreach($e as $k => $v) {
$value = GetArrayKey(array,$k);
print_r($value);
}
and it's printing the exact same value 5 times (but the $k that I am using to search for is different each time).
I'm assuming it is because of the return self::GetArrKey but I can't seem to fix it.
Examples...
tweet-19486731414564564
Tweet 1
tweet-19486778435455556
Tweet 1
tweet-19703966855465458
Tweet 1
tweet-19842914654654650
Tweet 1
But it should do
tweet-19486731414564564
Tweet 1
tweet-19486778435455556
Tweet 2
tweet-19703966855465458
Tweet 3
tweet-19842914654654650
Tweet 4

I believe your problem is in the last line of your recursive function:
return self::GetArrKey( $findArr[$key_arr[$depth]], $key_arr, $depth+1 );
This means that the function will be called again, until you hit a base case. The base case will return, and this function does not modify that case. Therefore all calls to the recursive function will return only the result of the base case, which is not what you want in this case because you're looking for a response rather than performing some function recursively.

Related

PHP class to find value in array from session

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;
}

How do array_udiff(), array_uintersect() etc. work?

There are a couple of similar questions here on SO, but I still haven't found an answer.
PHP manual states that
The comparison function must return an integer less than, equal to, or
greater than zero if the first argument is considered to be
respectively less than, equal to, or greater than the second.
The thing is that I don't understand why is it so important to have three optional outcomes, like -1, 0 and 1? Why wouldn't it work out if I used 0 for cases when two values being compared are equal and 1 otherwise?
A more practical question: I have a task where I should find elements of the first array that exist in the second one. The structures of the arrays are the same and look like the following:
Array
(
[0] => Array
(
[productId] => 5479046275
[options] => Array
(
[1] => All
[2] => Green
)
)
)
So I consider elements of such arrays equal when productId values match, and when there's no difference between options respecting their keys. Comparing options should be performed with the fact that 'All' options match every other's value. So I have a code like this:
$cartItems = <MyArray>;
$triggers = <MyAnotherArray>;
/**
* Options equal each other when they are exactly the same or
* when bundle offer's product has 'All' selected as option.
*/
$compareOptions = function ($a, $b) {
if ('All' == $b) {
return 0;
}
return strcmp($a, $b);
};
/**
* Compare product id to make sure these variants are of the same product
* Then check the options. If there's no difference, then variants
* are equal
*/
$compareVariants = function ($a, $b) use ($compareOptions) {
if ($a['productId'] != $b['productId']) {
return ($a['productId'] > $b['productId']) ? 1 : -1;
}
$optionsDiff = array_udiff_assoc($a['options'], $b['options'], $compareOptions);
if (0 === count($optionsDiff)) {
return 0;
} else {
return (count($optionsDiff) > 0) ? 1 : -1;
}
};
return array_uintersect($cartItems, $triggers, $compareVariants);
Then I xDebugged it. For some reason, when $optionsDiff is empty and script returns 0, it doesn't not step out of $compareVariants function, but goes to $compareOptions comparing arrays which produces a error.
Why does it work like that?
Thanks.
array_udiff_assoc() will compare the keys using built-in function and values will be compared using user-defined function.
array_udiff_assoc($array1,$array2,"userDefinedFunction");
So no matter what the result is. The user defined function will be called automatically to compare the array values. If you don't want to call your 'compareOptions' function, then you can go for array_diff_assoc($array1,$array2). This will use built in function to compare both keys and values of the arrays.

recursive array search for key in PHP

I am trying to do an array_search to find the associated value pair
I have an array called $saved_data it contains
Array () {
Client_Information_1 => James
Client_Information_2 => Doe
....
}
I need to return the value (1st call -> James .. 2nd call -> Doe .. etc) each time I call it. the problem is it's not returning the value pair back to me. The needle contains the index "Client_Information_1" .
my solution :
function recursive_array_search($saved_forms, $needle)
{
foreach($saved_forms as $key => $value)
{
if ( $saved_forms[$key] === $needle )
return $key;
}
return false;
}
function call in my loop :
$return_field = recursive_array_search($saved_data,$needle);
The $key is what you're searching for and $value is what you want to return (they value at that index)
So the if statement should look like this:
if ( $key === $needle ) {
return $value;
}
Since your function is not recursive at all or does anything else special, this'll do the same thing just fine:
$return_field = isset($saved_data[$needle]) ? $saved_data[$needle] : false;

PHP find the array index key of multi dimensional array to update array

I am trying to come up with a means of working with what could potentially be very large array sets. What I am doing is working with the facebook graph api.
So when a user signs up for a service that I am building, I store their facebook id in a table in my service. The point of this is to allow a user who signs up for my service to find friends of their's who are on facebook and have also signed up through my service to find one another easier.
What I am trying to do currently is take the object that the facebook api returns for the /me/friends data and pass that to a function that I have building a query to my DB for the ID's found in the FB data which works fine. Also while this whole bit is going on I have an array of just facebook id's building up so I can use them in an in_array scenario. As my query only returns facebook id's found matching
While this data is looping through itself to create the query I also update the object to contain one more key/value pair per item on the list which is "are_friends"=> false So far to this point it all works smooth and relatively fast, and I have my query results. Which I am looping over.
So I am at a part where I want to avoid having a loop within a loop. This is where the in_array() bit comes in. Since I created the array of stored fb id's I can now loop over my results to see if there's a match, and in that event I want to take the original object that I appended 'are_friends'=>false to and change the ones in that set that match to "true" instead of false. I just can't think of a good way without looping over the original array inside the loop that is the results array.
So I am hoping someone can help me come up with a solution here without that secondary loop
The array up to this point that starts off as the original looks like
Array(
[data](
[0] => array(
are_fb_friends => false
name => user name
id => 1000
)
[1] => array(
are_fb_friends => false
name => user name
id => 2000
)
[2] => array(
are_fb_friends => false
name => user name
id => 3000
)
)
)
As per request
This is my current code logic, that I am attempting to describe above..
public function fromFB($arr = array())
{
$new_arr = array();
if((is_array($arr))&&(count($arr) > 0))
{
$this->db->select()->from(MEMB_BASIC);
$first_pass = 0;
for($i=0;$i < count($arr);$i++)
{
$arr[$i]['are_fb_friends'] = "false";
$new_arr[] = $arr[$i]['id'];
if($first_pass == 0)
{
$this->db->where('facebookID', $arr[$i]['id']);
}
else
{
$this->db->or_where('facebookID', $arr[$i]['id']);
}
$first_pass++;
}
$this->db->limit(count($arr));
$query = $this->db->get();
if($query->num_rows() > 0)
{
$result = $query->result();
foreach($result as $row)
{
if(in_array($row->facebookID, $new_arr))
{
array_keys($arr, "blue");
}
}
}
}
return $arr;
}
To search a value and get its key in an array, you can use the array_search function which returns the key of the element.
$found_key = array_search($needle, $array);
For multidimensional array search in PHP look at https://stackoverflow.com/a/8102246/648044.
If you're worried about optimization I think you have to try using a query on a database (with proper indexing).
By the way, are you using the Facebook Query Language? If not give it a try, it's useful.

check is Array empty or not (php)

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
}

Categories