PHP in_array Find Any Matches
I am trying to figure out how to match any words within an array. For example, the code bellow works for finding «Test Name» within an array but does not find «Another Test Name» (due to the word «Another») within the array. Any ideas?
if (in_array($html[$i], $eventsarray)) < $topeventaa = "yes"; >else
6 Answers 6
If you want to match any of the words to those in your array, you may want to use explode on your string and then check each token as you do in your example.
We probably need more information, but you can create variable with the pattern matching you need with preg_match and pass it as the argument in your search.
preg_replace and str_replace may be helpful, depending on what exactly you’re trying to accomplish.
You may want to look into recursive function calls, like when traversing through all the directories within a directory tree. I’d splice the array up to the index where it was found, leaving the remainder to be passed back into the same function to search through again. Depending on what results you want from knowing the number of occurrences of words within a string could we then start to break down the problem and write some code.
Justin, there’s no direct way—no existing built-in function—to do what I believe you seek; you must iterate over the array yourself, along the lines of
$topeventaa = "no"; for ($eventsarray as $key=>$value) < if (0 >
Use preg_grep instead of in_array to find all elements of an array matching a given pattern.
This question is in a collective: a subcommunity defined by tags with relevant content and experts.
Finding values and keys in arrays
Check if a value or key exists in the array with in_array and array_key_exists functions respectively. Search the array by value and get first or all corresponding keys from the array with array_search and array_keys functions.
in_array()
The in_array() function returns true if an array $haystack contains a specific value $needle . The following example searches the array of integers $smallPrimes for the integer 19 :
A third, optional argument can be passed that enforces a strict type check when comparing each element with the needle. In the following example in_array() by default returns true ; however, with strict type checking, the string «19» doesn’t match the integer 19 held in the array and returns false :
array_search()
The array_search( ) function works the same way as the in_array( ) function, except the key of the matching value $needle is returned rather than the Boolean value true . However, if the value isn’t found, array_search( ) returns false .
The following code shows how array_search( ) works with both associative and indexed arrays:
1, "foot"=>12, "yard"=>36); echo array_search(12, $measure); //foot $units = array("inch", "centimeter", "chain", "furlong"); echo array_search("chain", $units); //2
Because array_search( ) returns a mixed result: the Boolean value false if the value isn’t found or the array key of the matching element. A problem is encountered when the first element is found in an indexed array, PHP’s automatic type conversion treats the value 0, the index of the first element, as false in a Boolean expression.
Care must be taken with functions, such as array_search() , that return a result or the Boolean value false to indicate when a result can’t be determined. If the return value is used as a Boolean (in an expression or as a Boolean parameter to a function) a valid result may be automatically converted to false . If such a function returns 0 , 0.0 , «c» , an empty string, or an empty array, PHP’s automatic type conversion converts the result to false when a Boolean value is required.
The correct way to test the result is to use the is-identical operator ===, as shown in the following example:
Note:
This function returns the first corresponding key for a given value, if you want to find all corresponding keys use array_keys() function instead.
array_keys()
This function returns all the keys of an array. If the optional $search_value argument is specified, you can get the keys for that particular value.
Example: Get all the keys from the array
1, 'two'=>2]; $keys = array_keys($a); print_r($keys); /* prints: Array ( [0] => 0 [1] => 1 [2] => 2 [3] => 3 [4] => one [5] => two ) */
Example: Search array by value and get corresponding keys
The following code shows how array_keys( ) works with both associative and indexed arrays:
1, 'two'=>2]; $keys = array_keys($a, 'red'); //[0,2] $b = ['one'=>'one', 1=>'one', 2=>'two']; $k = array_keys($b, 'one'); //['one',1]
Note:
Similar to in_array() and array_search() functions, a third, optional argument can be passed that enforces a strict type check when comparing each element with the needle.
array_key_exists()
The array_key_exists() function returns true if an array $array contains a specific key $key . The following example searches the array $numbers for the key two :
1, 'two'=>2, 'three'=>3, 'four'=>'four']; if ( array_key_exists('two', $numbers) ) echo 'The key "two" exists in the array $numbers'; else echo 'Key not found'; /* Prints: The key "two" exists in the array $numbers; */
Key can be any value possible for an array index:
array_values()
This function returns an indexed array with all the values of the original array. See Example:
1, 'two'=>2, 'three'=> 3]; //returns an indexed array $b = array_values($a); print_r($b); /*Prints Array ( [0] => 1 [1] => 2 [2] => 3 ) */
Working with arrays:
Check if all elements of array equal to something
Is there a php native function like in_array_all? If not, what would be the most elegant way to write such a func?
Should probably be called array_assert_elements( array $array, callable $callback ) instead of in_array_all as in_array works differently.
5 Answers 5
function in_array_all($value, $array)
function in_array_all($needle,$haystack) < if(empty($needle) || empty($haystack))< return false; >foreach($haystack as $k=>$v) < if($v != $needle)< return false; >> return true; >
And if you wanted to get really crazy:
function in_array_all($needle,$haystack) < if(empty($needle))< throw new InvalidArgumentException("$needle must be a non-empty string. ".gettype($needle)." given."); >if(empty($haystack) || !is_array($haystack)) < throw new InvalidArgumentException("$haystack must be a non-empty array. ".gettype($haystack)." given."); >foreach($haystack as $k=>$v) < if($v != $needle)< return false; >> return true; >
I don’t know the context of your code. But what about reversing the logic? Then you are able to use PHP’s native function in_array .
$my_arr_1 = array ("denied","denied","denied"); $my_arr_2 = array ("denied","denied","allowed"); !in_array("allowed", $my_arr_1); // => true !in_array("allowed", $my_arr_2); // => false
This entirely depends on your data set of course. But given the sample data, this would work. (Also, notice the negation ! in front of each method call to produce the desired boolean result).
Elegant way to search an PHP array using a user-defined function
The downside of this is that the code’s purpose is not immediately clear. Also, it won’t stop iterating over the array even if the element was found, although this is more of a nitpick (if the data set is large enough to cause problems, linear search won’t be an answer anyway)
Don’t you have to do the exact same thing in C++/Smalltalk/etc anyway, on the condition it wasn’t found? Or are you assuming there’ll always be at least one result?
It looks like you’re looking for PHP equivalent of JS (ES5, to be precise) Array.some method — but this method returns boolean, not an object.
Boolean return would be ok as well. @Izkata: Yes, you’re right of course, you can only stop iterating if there is a result — so it’s kind of a special case anyway. My bad.
Sometimes I temped to used such a function, but a standard foreach in a log of locations yield more concise an more readable code.
7 Answers 7
To pull the first one from the array, or return false :
current(array_filter($myArray, function($element) < . >))
@QuolonelQuestions All answers will be O(n) unless there’s been some preprocessing (sorting, hashing, etc)
@Izkata That’s patently false. The search should stop once the element has been found. Your crude code continues to process every element regardless of when a match is found.
A straightforward implementation with foreach would have O(1) best case, O(n) worst case. This is O(n) in both cases. Also, O(n) space complexity instead of O(1) (ie. the whole array might get duplicated in memory).
function array_find($xs, $f) < foreach ($xs as $x) < if (call_user_func($f, $x) === true) return $x; >return null; > array_find([1,2,3,4,5,6], function($x) < return $x >4; >); // 5 array_find([1,2,3,4,5,6], function($x) < return $x >10; >); // null
In the event $f($x) returns true , the loop short circuits and $x is immediately returned. Compared to array_filter , this is better for our use case because array_find does not have to continue iterating after the first positive match has been found.
In the event the callback never returns true, a value of null is returned.
Note, I used call_user_func($f, $x) instead of just calling $f($x) . This is appropriate here because it allows you to use any compatible callable
Class Foo < static private $data = 'z'; static public function match($x) < return $x === self::$data; >> array_find(['x', 'y', 'z', 1, 2, 3], ['Foo', 'match']); // 'z'
Of course it works for more complex data structures too
$data = [ (object) ['id' => 1, 'value' => 'x'], (object) ['id' => 2, 'value' => 'y'], (object) ['id' => 3, 'value' => 'z'] ]; array_find($data, function($x) < return $x->id === 3; >); // stdClass Object ( // [id] => 3 // [value] => z // )
If you’re using PHP 7, add some type hints
function array_find(array $xs, callable $f) < .
Regarding your last piece of code, array and callable type hinting have been in PHP since 5.1.0 and 5.4.0 respectively.
You can only hint selected types in older PHP. Writing inconsistent code isn't a recommendation I would make.
I know this is a minor nitpick and most people won't care, but I'd probably have called the arguments $array and $comparator so you can actually tell what they are from the signature. Definitely the most straight forward solution, and the one I tend to go with, though.
The original array_search returns the key of the matched value, and not the value itself (this might be useful if you're will to change the original array later).
try this function (it also works will associatives arrays)
function array_search_func(array $arr, $func) < foreach ($arr as $key =>$v) if ($func($v)) return $key; return false; >
I like this. FWIW, I named my version of this first_key , to remind myself that it returns the key not the value .
Pulled from Laravel's Illuminate\Collections\Arr::first method:
if (!function_exists('array_first')) < /** * Return the first element in an array passing a given truth test. * * @param iterable $array * @param callable|null $callback * @param mixed $default * @return mixed */ function array_first($array, callable $callback = null, $default = null) < if (is_null($callback)) < if (empty($array)) < return $default; >foreach ($array as $item) < return $item; >> foreach ($array as $key => $value) < if ($callback($value, $key)) < return $value; >> return $default; > >
I think it's pretty good. There is also the Illuminate\Collections\Arr::last method, but it's probably not as optimized since it reverses the array and just calls the first method. It does get the job done, though.
if (!function_exists('array_last')) < /** * Return the last element in an array passing a given truth test. * * @param array $array * @param callable|null $callback * @param mixed $default * @return mixed */ function array_last($array, callable $callback = null, $default = null) < if (is_null($callback)) < return empty($array) ? $default : end($array); >return array_first(array_reverse($array, true), $callback, $default); > >
Pro-tip: If you have an array of objects, then you can specify the type of the callback's argument for that sweet IDE auto-completion.
$john = array_first($users, function(User $user) < return $user->name === 'John'; >); // Works with pretty much anything. $activeUsers = array_filter($users, function(User $user) < return $user->isActive; >); // Class example: class User < public string $name; public bool $isActive; //. >
If you want to use some variable from the outer scope, you can use the use(&$var) syntax like this
foreach($values as $key => $value) < array_find($conditionsRecords, function($row) use(&$key) < $keyToFind = $key; return $keyToFind; >) >