To pull the first one from the array, or return false:
current(array_filter($myArray, function($element) { ... }))
More info on current() here.
Answer from Izkata on Stack OverflowTo pull the first one from the array, or return false:
current(array_filter($myArray, function($element) { ... }))
More info on current() here.
Here's a basic solution
function array_find(
f) {
foreach (
x) {
if (call_user_func(
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 returns x)
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( instead of just calling x)
. This is appropriate here because it allows you to use any compatible callablex)
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) { ...
If your array may contain null elements, array_find cannot return null to signal no element was not found. As @dossy suggests, you could use an array result containing either one or zero elements -
function array_find(
f) {
foreach (
x) {
if (call_user_func(
x) === true)
return [$x]; // result
}
return []; // not found
}
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; }); // []
What does PHP array_find do?
array_find function searches through an array and returns
the first element that matches a condition.
Example:
$result = array_find([1, 2, 3, 4], function($n) {
return $n > 2;
});
echo $result; // Output: 3How is PHP array_find different from array_filter?
array_findreturns the first matching value.array_filterreturns all matching values.
$array = [1, 2, 3, 4, 5];
$find = array_find($array, fn($n) => $n > 3);
echo $find; // Output: 4
$filter = array_filter($array, fn($n) => $n > 3);
print_r($filter); // Output: [4, 5]How to write a custom PHP array_find function?
array_find function that works with
any type of array.
Example:
function array_find($array, $callback) {
foreach ($array as $key => $value) {
if ($callback($value, $key)) {
return $value;
}
}
return null;
}
$numbers = [10, 20, 30, 40];
$result = array_find($numbers, fn($n) => $n === 30);
echo $result; // Output: 30array_filter gets you all items that match a given condition, but what I want is to get the first such item
Let's say I want to display a link to a country's capital, given an ID number and a query of the country's cities.
I could do something like
echo $country["Capital"] ?
cityToLink(
array_filter($cities,
function($city){
global $country;
return $city["ID"] == $country["Capital"];
}
)[0]):
"N/A"but that falls apart if the index of the needed city isn't 0, since it seems that array_filter keeps the original indexes intact
Why don't you make your cities array indexed by id?
Looks like you got a solution, but for the record, there is no equivalent function, your solution using array filter is the closest one possible but it's also kind of "clever" and that's considered bad practice because it makes it harder for others to read.
Luckily it's very easy to implement...
function array_find(callable $callback, array $array) {
foreach ($array as $key => $value) {
if ($callback($value, $key, $array)) {
return $value;
}
}
}
Writing that once is cleaner looking and takes about the same amount of lines as doing it in-place like so:
$found = null;
foreach ($array as $key => $value) {
if (/* condition is met */) {
$found = $value;
break;
}
}
I work on many codebases where I see that form of the same concept repeated hundreds of times because nobody wanted or thought to write a helper function or use a library that provided one.
Speaking of which, there are many collection classes that provide wrappers around arrays and make them easier to deal with, I've used and like Knapsack.