Being new to PHP and its arrays I wonder if there is a better way of doing a simple search like this:
$found = "0";
foreach ($myArray as $item) {
if ($item->id == "Foo") {
$found = $item->value;
break;
}
}
Another solution would be to use array_filter:
$matchingArray = array_filter($myArray, function($object) {
return $object->id == 'Foo';
});
It will iterate on your array, and call the provided callback (second parameter) with each element in your array. The callback needs to return true, if the item matches your needs, false otherwise.
If you only need the first one:
if(count($matchingArray) > 0){
$firstMatch = $matchingArray[0];
}else{
// none found.
}
You can use
array_search()
or you can simply use:
if(in_array($foo, $bar)
where $foo is a value to look for and $bar is an array
Related
I know how to use loop to do this simple problem, but I want to play more with recursion. I trying to find max value in array using recursion with PHP. My basic idea is compare the first value of the array with the maximum value of the new array (made by remove the first value of the given array):
function find_max($arr)
{
if ($arr = [])
{
return 0; // base case
} else
{
if ($arr[0] > find_max(rest_of($arr)))
{
return $arr[0];
} else
{
return find_max(rest_of($arr));
}
}
}
function rest_of($arr)
{
unset($arr[0]); // remove the first value of the array
$arr = array_values($arr); // re-index the array
return $arr;
}
But when I run, it seems that it has infinite loop. "Undefined offset: 0"
Can anyone help me?
The problem is because of your base condition here,
if($arr = []){ ...
= is an assignment operator, not comparison operator. What you need here is a comparison operator ==. So it should be,
if($arr == []){
Furthermore, you can change your base condition like this way,
if(count($arr) == 1){
return $arr[0]; // base case
}
So your find_max() function should be like this:
function find_max($arr){
if(count($arr) == 1){
return $arr[0]; // base case
}
if ($arr[0] > find_max(rest_of($arr))){
return $arr[0];
} else{
return find_max(rest_of($arr));
}
}
on http://php.net/manual/en/function.in-array.php - if you scroll down it gives a function to determine if a string is inside of a query in a multidimensional array. "If you found yourself in need of a multidimensional array in_array like function you can use the one below. Works in a fair amount of time"
Here's original code(working):
function in_multiarray($elem, $array)
{
$top = sizeof($array) - 1;
$bottom = 0;
while($bottom <= $top)
{
if($array[$bottom] == $elem)
return true;
else
if(is_array($array[$bottom]))
if(in_multiarray($elem, ($array[$bottom])))
return true;
$bottom++;
}
return false;
}
What I'm trying to do is instead of returning 'true' or 'false' - i'd like to return the ROW #. So my initial thought was to simply replace 'return true' with 'return $bottom; however it isn't returning the record number.
Modified Function (not working);
function in_multiarray($elem, $array)
{
$top = sizeof($array) - 1;
$bottom = 0;
while($bottom <= $top)
{
if($array[$bottom] == $elem)
return $bottom;
else
if(is_array($array[$bottom]))
if(in_multiarray($elem, ($array[$bottom])))
return $bottom;
$bottom++;
}
return false;
}
Does anyone have an idea how to modify this function to return the ROW number that contains the match?
Here's a sample of the array...
$sample = array
array ("oldpage1.php","newpage1.php"),
array ("oldpage2.php","newpage2.php"),
array ("oldpage3.php","newpage3.php"),
array ("oldpage4.php","newpage4.php"),
array ("oldpage5.php","newpage5.php")
etc.
);
$row = in_multiarray($input, $sample);
Therefore if we know the row # we can fetch the new page with a simple
$newpage=$sample[$row][1]
Thanks!
It's worth noting that a function like in_array is intended to tell you whether or not a value exists inside of an array. What you're looking for seems to be a lot closer to something like array_search, which is designed to actually provide you with the key that points to a given value in the array.
However, because you're using a multi-dimensional array what you're actually looking for is the key that points to the array that contains the value. Hence we can divide and conquer this problem with two simple steps.
Map
Filter
The first step is to map a function in_array to every element in the first array (which is just another array). This will tell us which elements of the primary array contain an array that contains the value we're searching for.
$result = array_map(function($arr) use($search) {
return in_array($search, $arr, true);
}, $arr, [$searchValue]);
The second step is to then return the keys to those arrays (i.e. filter the result).
$keys = array_keys(array_filter($result));
Now you have all the keys of any matching items. If you want to apply as just one custom filter that specifies exactly where in the subarray to look, you could also do it like this.
$search = "oldpage2.php";
$sample = [
["oldpage1.php","newpage1.php"],
["oldpage2.php","newpage2.php"],
["oldpage3.php","newpage3.php"],
["oldpage4.php","newpage4.php"],
["oldpage5.php","newpage5.php"],
];
$keys = array_keys(array_filter($sample, function($arr) use($search) {
return $arr[0] === $search;
}));
var_dump($keys);
And you get...
array(1) {
[0]=>
int(1)
}
So now you know that "oldpage2.php" is in row 1 in $sample[1][0] which means you can do this to get the results out of the array.
foreach($keys as $key) {
echo "{$sample[$key][0]} maps to {$sample[$key][1]}\n";
}
Giving you
oldpage2.php maps to newpage2.php
If you want to return only the first result you could do that as well with a function like this using similar approach.
function getFirstMatch($search, Array $arr) {
foreach($arr as $key => $value) {
if ($value[0] === $search) {
return $value[1];
}
}
}
echo getFirstMatch("oldpage4.php", $sample); // newpage4.php
The Better Alternative
Of course, the better approach is to actually use the oldpage names as the actual keys of the array rather than do this expensive search through the array, because array lookup by key in PHP is just an O(1) operation, whereas this needle/haystack approach is O(N).
So we turn your $samples array into something like this and the search no longer requires any functions...
$samples = [
"oldpage1.php" => "newpage1.php",
"oldpage2.php" => "newpage2.php",
"oldpage3.php" => "newpage3.php",
"oldpage4.php" => "newpage4.php",
"oldpage5.php" => "newpage5.php",
];
Now you can just do something like $newpage = $samples[$search] and you get exactly what you're looking for. So echo $samples["oldpage2.php"] gives you "newpage2.php" directly without the intermediary step of searching through each array.
You can use the following code to get the full path to the value:
function in_multiarray($elem, $array, &$result)
{
$top = sizeof($array) - 1;
$bottom = 0;
while($bottom <= $top)
{
if($array[$bottom] == $elem) {
array_unshift($result, $bottom);
return true;
}
else {
if(is_array($array[$bottom])) {
if(in_multiarray($elem, $array[$bottom], $result)) {
array_unshift($result, $bottom);
return true;
}
}
}
$bottom++;
}
array_shift($result);
return false;
}
$sample = array(
array ("oldpage1.php","newpage1.php"),
array ("oldpage2.php","newpage2.php"),
array ("oldpage3.php","newpage3.php"),
array ("oldpage4.php","newpage4.php"),
array ("oldpage5.php","newpage5.php")
);
$input = "newpage5.php";
$result = [];
in_multiarray($input, $sample, $result);
print_r($result);
Path is stored in $result;
I have no idea what keyword should I use on google to find the solution.
This is my code:
function getArray(){
return array('one','two','three');
}
$array = getArray();
echo $array[2];
My question is there a more efficient way to print the third element from the returned array?
If you want the easiest way to print the x-th element of the array, you should use a parameter in your function.
This way you can also do some checks to see if the index is valid.
function getArray($index){
$array = ['one', 'two', 'three'];
if ($index < 0 || $index >= count($array)) {
return null;
} else {
return $array[$index];
}
}
echo getArray(2);
I'm trying to find a part of a string in a multidimentional array.
foreach ($invitees as $invitee) {
if (in_array($invitee, $result)){
echo 'YES';
} else {
echo 'NO';
}
}
the $invitees array has 2 elements:
and $result is what I get from my Drupal database using db_select()
What I'm trying to do is, if the first part from one of the emails in $invitees is in $result it should echo "YES". (the part before the "#" charather)
For example:
"test.email" is in $result, so => YES
"user.one" is not in $result, so => NO
How do i do this? How can I search for a part of a string in a multidimentional array?
Sidenote: I noticed that the array I get from Drupal ($result) has 2 "Objects" which contain a "String", and not arrays like I would expect.
For example:
$test = array('red', 'green', array('apple', 'banana'));
Difference between $result and $test:
Does this have any effect on how I should search for my string?
Because $result is an array of objects, you'll need to use a method to access the value and compare it. So, for instance you could do:
//1: create new array $results from array of objects in $result
foreach ($result as $r) {
$results[] = get_object_vars($r);
}
//2: expanded, recursive in_array function for use with multidimensional arrays
function in_array_r($needle, $haystack, $strict = false) {
foreach ($haystack as $item) {
if (($strict ? $item === $needle : $item == $needle) || (is_array($item) && in_array_r($needle, $item, $strict))) {
return true;
}
}
return false;
}
//3: check each element of the $invitees array
foreach ($invitees as $invitee) {
echo in_array_r($invitee, $results) ? "Yes" : "No";
}
Also, for some illumination, check out this answer.
You can search through the array using preg_grep, and use a wildcard for anything before and after it. If it returns a value (or values), use key to get the index of the first one. Then do a check if its greater than or equal to 0, which means it found a match :)
<?php
$array = array('test1#gdfgfdg.com', 'test2#dgdgfdg.com', 'test3#dfgfdgdfg');
$invitee = 'test2';
$result = key(preg_grep('/^.*'.$invitee.'.*/', $array));
if ($result >= 0) {
echo 'YES';
} else {
echo 'NO';
}
?>
Accepted larsAnders's answer since he pointed me in to direction of recursive functions.
This is what I ended up using (bases on his answer):
function Array_search($array, $string) {
foreach ($array as $key => $value) {
if (is_array($value)) {
Array_search($array[$key], $string);
} else {
if ($value->data == $string) {
return TRUE;
}
}
}
return FALSE;
}
1. PHP function.
I've created validating function, here it is in shorter version:
function my_function($input) {
$settings = my_source(); // function taht outputs a long array
foreach ($settings as $setting) {
$id = $setting['id'];
$foo = $setting['foo'];
$option = get_option('my_theme_settings');
if($foo == "bar") {
$valid_input[$id] = $input[$id];
}
}
return $valid_input;
};
Basically it takes $input and saves it as $valid_input. When it gets new $input it overwrites the old #valid_inpu and so on.
I want to create an additional $valid_input[$id] array that will not overwrite itself, but just push new elements inside.
2. Array_push() that doesn't work.
So the new updated code will look like that:
function my_function($input) {
$settings = my_source(); // function taht outputs a long array
foreach ($settings as $setting) {
$id = $setting['id'];
$foo = $setting['foo'];
$option = get_option('my_theme_settings');
if($foo == "bar") {
$valid_input[$id] = $input[$id];
}
else if($foo == "noupdate") { // it doesn't work
$valid_input[$id] = array();
array_push($valid_input[$id], $input[$id]);
}
}
return $valid_input;
};
As mentioned in comment above - this doesn't work, input always overwrites the option, it creates an array but it always contains only one element that is being erased with the new one (I guess array_push should prevent that behavior, right?).
3. The same happens with $array[] =
function my_function($input) {
$settings = my_source(); // function taht outputs a long array
foreach ($settings as $setting) {
$id = $setting['id'];
$foo = $setting['foo'];
$option = get_option('my_theme_settings');
if($foo == "bar") {
$valid_input[$id] = $input[$id];
}
else if($foo == "noupdate") { // it doesn't work
$valid_input[$id][] = $input[$id];
}
}
return $valid_input;
};
Still it overwrites the old value of $valid_input instead of pushing an element.
Any ideas? Maybe there's something wrong with the code? This whole function a Wordpress callback for function called register_setting(), but I guess it's mostly PHP related as folks on WPSE can't help me.
4. EDIT
This does exactly what I want, but why point 3. doesn't work then?
else if($foo == "noupdate") { // it doesn't work
$valid_input[$id][] = 'something';
$valid_input[$id][] = 'something_else';
$valid_input[$id][] = 'something_else2';
}
$valid_input[$id] needs to be set to array before you treat it as one.
$valid_input[$id] = array();
array_push( $valid_input[$id], "some stuff");
Same deal with [] notation
$valid_input[$id] = array();
$valid_input[$id][] = "some stuff";
To check if the array has been declared, so this:
if(!is_array($valid_input[$id]){
$valid_input[$id] = array();
}
The thing is that objects are passed as reference. you need to clone the objects before using the array_push function. here is a sample function that will clone an object:
function DeepCopy($ObjectToCopy) {
return unserialize(serialize($ObjectToCopy));
}
then you can use it this way
array_push($MyObjectsArray, DeepCopy($MyObject));
is it possible that you are trying to push a new value to the array with a key value that already exists? i would test for an existing key value in your array before trying to push a value/key pair to it. example:
if ( !isset( $arr[ $key ] ) ) {
$arr[ $key ] = $value;
} else {
echo " duplicate key value ";
}
Either array_push() or a variable used with the array append operator [] need to actually be an array or these won't work. Double check that whatever is in $valid_input[$id] is an array before doing array operations on the variable. Check by doing:
if (is_array($valid_input[$id])) {
// your code
}