Code:
function search($array, $key, $value)
{
$results = array();
if (is_array($array)) {
if (isset($array[$key]) && $array[$key] == $value) {
$results[] = $array;
}
foreach ($array as $subarray) {
$results = array_merge($results, search($subarray, $key, $value));
}
}
return $results;
}
$arr = array(0 => array(id=>1,name=>"cat 1"),
1 => array(id=>2,name=>"cat 2"),
2 => array(id=>3,name=>"cat 1"));
print_r(search($arr, 'name', 'cat 1'));
Production:
Array
(
[0] => Array
(
[id] => 1
[name] => cat 1
)
[1] => Array
(
[id] => 3
[name] => cat 1
)
)
Si l'efficacité est importante, vous pouvez l'écrire pour que tous les appels récursifs stockent leurs résultats dans le même $results
tableau temporaire plutôt que de fusionner des tableaux ensemble, comme ceci:
function search($array, $key, $value)
{
$results = array();
search_r($array, $key, $value, $results);
return $results;
}
function search_r($array, $key, $value, &$results)
{
if (!is_array($array)) {
return;
}
if (isset($array[$key]) && $array[$key] == $value) {
$results[] = $array;
}
foreach ($array as $subarray) {
search_r($subarray, $key, $value, $results);
}
}
La clé là-bas search_r
prend son quatrième paramètre par référence plutôt que par valeur; l'esperluette &
est cruciale.
FYI: Si vous avez une ancienne version de PHP, vous devez spécifier la partie pass-by-reference dans l' appel à search_r
plutôt que dans sa déclaration. Autrement dit, la dernière ligne devient search_r($subarray, $key, $value, &$results)
.
$key
ne sortira- t-elle pas si elle n'existe pas dans le tableau? Ne serait-il pas préférable de le faireif (array_key_exists($key, $array) && $array[$key] == $value) {
?$value
qui estnull
et la fonction ne fonctionne pas ...array empty
... Comment avoir un tableau même si$value
=null
? commesearch($array, 'id', null)
?Que diriez - vous de la SPL la version à la place? Cela vous évitera de taper:
Ce qui est génial, c'est que fondamentalement, le même code itérera dans un répertoire pour vous, en utilisant un RecursiveDirectoryIterator au lieu d'un RecursiveArrayIterator. SPL est le roxor.
Le seul inconvénient de SPL est qu'il est mal documenté sur le Web. Mais plusieurs livres PHP donnent des détails utiles, en particulier Pro PHP; et vous pouvez probablement rechercher plus d'informations sur Google.
la source
Réf: http://php.net/manual/en/function.array-filter.php
la source
Je suis revenu pour publier cette mise à jour pour tous ceux qui ont besoin d'un conseil d'optimisation sur ces réponses, en particulier la grande réponse de John Kugelman ci-dessus.
Sa fonction publiée fonctionne bien, mais j'ai dû optimiser ce scénario pour gérer un ensemble de résultats de 12 000 lignes. La fonction prenait un éternel 8 secondes pour parcourir tous les enregistrements, waaaaaay trop longtemps.
J'avais simplement besoin de la fonction pour arrêter la recherche et revenir lorsque la correspondance était trouvée. Par exemple, si vous recherchez un customer_id, nous savons que nous n'en avons qu'un dans le jeu de résultats et une fois que nous avons trouvé le customer_id dans le tableau multidimensionnel, nous voulons revenir.
Voici la version à vitesse optimisée (et très simplifiée) de cette fonction, pour toute personne dans le besoin. Contrairement aux autres versions, il ne peut gérer qu'une seule profondeur de tableau, ne se répète pas et supprime la fusion de plusieurs résultats.
Cela a réduit la tâche de faire correspondre les 12 000 enregistrements à 1,5 seconde. Toujours très coûteux mais beaucoup plus raisonnable.
la source
Une amélioration mineure de la version rapide.
la source
Faites attention aux algorithmes de recherche linéaire (ceux ci-dessus sont linéaires) dans des tableaux multidimensionnels car ils ont aggravé la complexité car sa profondeur augmente le nombre d'itérations nécessaires pour parcourir le tableau entier. Par exemple:
prendrait au plus 200 itérations pour trouver ce que vous cherchez (si l'aiguille était à [100] [1]), avec un algorithme approprié.
Les algorithmes linéaires dans ce cas fonctionnent à O (n) (ordre du nombre total d'éléments dans le tableau entier), c'est médiocre, un million d'entrées (par exemple un tableau de 1000x100x10) prendrait en moyenne 500000 itérations pour trouver l'aiguille. Que se passerait-il également si vous décidiez de changer la structure de votre tableau multidimensionnel? Et PHP lancerait un algorithme récursif si votre profondeur était supérieure à 100. L'informatique peut faire mieux:
Dans la mesure du possible, utilisez toujours des objets au lieu de tableaux à plusieurs dimensions:
et appliquez une interface et une fonction de comparateur personnalisées pour les trier et les trouver:
Vous pouvez utiliser
uasort()
pour utiliser un comparateur personnalisé, si vous vous sentez aventureux, vous devez implémenter vos propres collections pour vos objets qui peuvent les trier et les gérer (j'étends toujours ArrayObject pour inclure au moins une fonction de recherche).Une fois qu'ils sont triés (uasort est O (n log n), ce qui est aussi bon que sur des données arbitraires), la recherche binaire peut effectuer l'opération en temps O (log n), c'est-à-dire qu'un million d'entrées ne prend que ~ 20 itérations pour chercher. Autant que je sache, la recherche binaire de comparateur personnalisé n'est pas implémentée en PHP (
array_search()
utilise un ordre naturel qui fonctionne sur les références d'objet et non sur leurs propriétés), vous devrez l'implémenter vous-même comme je le fais.Cette approche est plus efficace (il n'y a plus de profondeur) et surtout universelle (en supposant que vous appliquez la comparabilité à l'aide d'interfaces) puisque les objets définissent comment ils sont triés, vous pouvez donc recycler le code à l'infini. Beaucoup mieux =)
la source
Voici la solution:
la source
la source
http://snipplr.com/view/51108/nested-array-search-by-value-or-key/
la source
la source
J'avais besoin de quelque chose de similaire, mais pour rechercher un tableau multidimensionnel par valeur ... j'ai pris l'exemple de John et j'ai écrit
J'espère que cela aide quelqu'un :)
la source
Ceci est une fonction révisée de celle que John K. a publiée ... Je n'ai besoin de saisir que la clé spécifique du tableau et rien au-dessus.
la source
Et une autre version qui renvoie la valeur clé de l'élément du tableau dans lequel la valeur est trouvée (pas de récursivité, optimisée pour la vitesse):
Merci à tous ceux qui ont posté ici.
la source
la source
Si vous voulez rechercher un tableau de clés, c'est bien
Les clés ne seront pas écrasées car chaque ensemble de valeurs key => sera dans un tableau séparé dans le tableau résultant.
Si vous ne voulez pas de clés en double, utilisez celle-ci
la source