En gros, je veux pouvoir obtenir les fonctionnalités de find_if()
de C++, de detect:
de Smalltalk, etc.:
// would return the element or null
check_in_array($myArray, function($element) { return $elemnt->foo() > 10; });
Mais je ne connais aucune fonction PHP qui effectue cela. Une "approximation" je suis venu avec:
$check = array_filter($myArray, function($element) { ... });
if ($check)
//...
L'inconvénient est que le but du code n'est pas clair. De plus, cela n'arrêtera pas d'itérer sur le tableau même si l'élément a été trouvé, bien que ce soit plus qu'un nitpick (si le jeu de données est assez grand pour causer des problèmes, la recherche linéaire ne sera de toute façon pas une réponse)
Pour extraire le premier du tableau ou renvoyer false
:
current(array_filter($myArray, function($element) { ... }))
Voici une solution de base
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
Si l'événement $f($x)
renvoie true
, la boucle est court-circuitée et $x
est immédiatement renvoyé. Comparé à array_filter
, cela est préférable pour notre cas d'utilisation car array_find
ne doit pas continuer à itérer après la première correspondance positive.
Si le rappel ne renvoie jamais la valeur true, la valeur null
est renvoyée.
Remarque, j'ai utilisé call_user_func($f, $x)
au lieu d'appeler simplement $f($x)
. Ceci est approprié ici car il vous permet d'utiliser n'importe quel 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'
Bien sûr, cela fonctionne aussi pour les structures de données plus complexes
$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
// )
Si vous utilisez PHP 7, ajoutez des conseils de type.
function array_find(array $xs, callable $f) { ...
Le array_search
d'origine renvoie la clé de la valeur correspondante, et non la valeur elle-même (cela peut être utile si vous souhaitez modifier le tableau d'origine ultérieurement).
essayez cette fonction (cela fonctionne aussi avec les tableaux associatifs)
function array_search_func(array $arr, $func)
{
foreach ($arr as $key => $v)
if ($func($v))
return $key;
return false;
}
Vous pouvez écrire une telle fonction vous-même, même s’il ne s’agit guère que d’une boucle.
Par exemple, cette fonction vous permet de passer une fonction de rappel. Le rappel peut renvoyer 0 ou une valeur. Le rappel que je spécifie renvoie l'entier s'il est> 10. La fonction s'arrête lorsque le rappel renvoie une valeur non NULL.
function check_in_array(array $array, $callback)
{
foreach($array as $item)
{
$value = call_user_func($callback, $item);
if ($value !== null)
return $value;
}
}
$a = array(1, 2, 3, 6, 9, 11, 15);
echo check_in_array($a, function($i){ return ($i > 10?$i:null); });
Utilisez \iter\search()
de la bibliothèque d'iters des fonctions d'itération primitives de nikic. Il présente l'avantage supplémentaire de fonctionner sur les collections de tableaux etTraversable
.
$foundItem = \iter\search(function ($item) {
return $item > 10;
}, range(1, 20));
if ($foundItem !== null) {
echo $foundItem; // 11
}