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: 30For the canonical reference:
$obj = array_column($array, null, 'id')['one'] ?? false;
The false is per the question's requirement to return false. It represents the nonmatching value, e.g., you can make it null for example as an alternative suggestion.
This works transparently since PHP 7.0. In case you (still) have an older version, there are user-space implementations of it that can be used as a drop-in replacement.
However array_column also means to copy a whole array. This might not be wanted.
Instead it could be used to index the array and then map over with array_flip:
$index = array_column($array, 'id');
$map = array_flip($index);
$obj = $array[$map['one'] ?? null] ?? false;
On the index, the search problem might still be the same. The map just offers the index in the original array, so there is a reference system.
Keep in mind though that this might not be necessary as PHP has copy-on-write. So there might be less duplication as intentionally thought. So this is to show some options.
Another option is to go through the whole array and unless the object is already found, check for a match. One way to do this is with array_reduce:
$obj = array_reduce($array, static function ($carry, $item) {
return $carry === false && $item->id === 'one' ? $item : $carry;
}, false);
This variant again is with the returning false requirement for no-match.
It is a bit more straight forward with null:
$obj = array_reduce($array, static function ($carry, $item) {
return $carry ?? ($item->id === 'one' ? $item : $carry);
}, null);
And a different no-match requirement can then be added with $obj = ...) ?? false; for example.
Fully exposing to foreach within a function of its own even has the benefit to directly exit on match:
$result = null;
foreach ($array as $object) {
if ($object->id === 'one') {
$result = $object;
break;
}
}
unset($object);
$obj = $result ?? false;
This is effectively the original answer by hsz, which shows how universally it can be applied.
You can iterate that objects:
function findObjectById($id){
$array = array( /* your array of objects */ );
foreach ( $array as $element ) {
if ( $id == $element->id ) {
return $element;
}
}
return false;
}
Faster way is to have an array with keys equals to objects' ids (if unique);
Then you can build your function as follow:
function findObjectById($id){
$array = array( /* your array of objects with ids as keys */ );
if ( isset( $array[$id] ) ) {
return $array[$id];
}
return false;
}
Another poossible solution is based on the array_search() function. You need to use PHP 5.5.0 or higher.
Example
$userdb=Array
(
0 => Array
(
"uid" => '100',
"name" => 'Sandra Shush',
"url" => 'urlof100'
),
1 => Array
(
"uid" => '5465',
"name" => 'Stefanie Mcmohn',
"pic_square" => 'urlof100'
),
2 => Array
(
"uid" => '40489',
"name" => 'Michael',
"pic_square" => 'urlof40489'
)
);
$key = array_search(40489, array_column($userdb, 'uid'));
echo ("The key is: ".$key);
//This will output- The key is: 2
Explanation
The function `array_search()` has two arguments. The first one is the value that you want to search. The second is where the function should search. The function `array_column()` gets the values of the elements which key is `'uid'`.Summary
So you could use it as:array_search('breville-one-touch-tea-maker-BTM800XL', array_column($products, 'slug'));
or, if you prefer:
// define function
function array_search_multidim($array, $column, $key){
return (array_search($key, array_column($array, $column)));
}
// use it
array_search_multidim($products, 'slug', 'breville-one-touch-tea-maker-BTM800XL');
The original example(by xfoxawy) can be found on the DOCS.
The array_column() page.
Update
Due to Vael comment I was curious, so I made a simple test to meassure the performance of the method that uses array_search and the method proposed on the accepted answer.
I created an array which contained 1000 arrays, the structure was like this (all data was randomized):
[
{
"_id": "57fe684fb22a07039b3f196c",
"index": 0,
"guid": "98dd3515-3f1e-4b89-8bb9-103b0d67e613",
"isActive": true,
"balance": "$2,372.04",
"picture": "http://placehold.it/32x32",
"age": 21,
"eyeColor": "blue",
"name": "Green",
"company": "MIXERS"
},...
]
I ran the search test 100 times searching for different values for the name field, and then I calculated the mean time in milliseconds. Here you can see an example.
Results were that the method proposed on this answer needed about 2E-7 to find the value, while the accepted answer method needed about 8E-7.
Like I said before both times are pretty aceptable for an application using an array with this size. If the size grows a lot, let's say 1M elements, then this little difference will be increased too.
Update II
I've added a test for the method based in array_walk_recursive which was mentionend on some of the answers here. The result got is the correct one. And if we focus on the performance, its a bit worse than the others examined on the test. In the test, you can see that is about 10 times slower than the method based on array_search. Again, this isn't a very relevant difference for the most of the applications.
Update III
Thanks to @mickmackusa for spotting several limitations on this method:
- This method will fail on associative keys.
- This method will only work on indexed subarrays (starting from 0 and have consecutively ascending keys).
Note on Update III
- not taking performance into account: you can use array_combine with array_keys & array_column to overcome this limitation in a one-liner like:
$product_search_index =
array_search( 'breville-one-touch-tea-maker-BTM800XL', array_filter( array_combine( array_keys($products), array_column( $products, 'slug' ) ) ) );
Very simple:
function myfunction($products, $field, $value)
{
foreach($products as $key => $product)
{
if ( $product[$field] === $value )
return $key;
}
return false;
}