478 votes

Recherche par valeur dans un tableau multidimensionnel en PHP

J'ai un tableau dans lequel je veux rechercher les éléments suivants uid et obtenir la clé du tableau.

Exemples

Supposons que nous ayons le tableau à deux dimensions suivant :

$userdb = array(
    array(
        'uid' => '100',
        'name' => 'Sandra Shush',
        'pic_square' => 'urlof100'
    ),
    array(
        'uid' => '5465',
        'name' => 'Stefanie Mcmohn',
        'pic_square' => 'urlof100'
    ),
    array(
        'uid' => '40489',
        'name' => 'Michael',
        'pic_square' => 'urlof40489'
    )
);

L'appel de fonction search_by_uid(100) (uid du premier utilisateur) devrait renvoyer 0 .

L'appel de fonction search_by_uid(40489) doit renvoyer 2 .

J'ai essayé de faire des boucles, mais je veux un code qui s'exécute plus rapidement.

0 votes

Il est intéressant de noter que les bibliothèques underscore (et lowdash) ajoutent cette fonction à javascript...

12 votes

J'ai écrit un script pour tester la performance de quelques réponses. Il génère un tableau de tableaux de 500k membres et le parcourt à la recherche d'une valeur dans le dernier membre. J'ai comparé une fonction comme la réponse acceptée, aux deux fonctions suivantes array_column des réponses en une ligne. Je les ai toutes modifiées pour qu'elles renvoient le tableau découvert, et pas seulement la clé, car c'est généralement ce que j'utilise. La méthode function a obtenu un score de 0,361, search-col 0,184 et keys-col 0,189 micro délai moyen sur 1000 exécutions pour chaque méthode.

663voto

Jakub Truneček Points 1529
function searchForId($id, $array) {
   foreach ($array as $key => $val) {
       if ($val['uid'] === $id) {
           return $key;
       }
   }
   return null;
}

Cela fonctionnera. Vous devriez l'appeler ainsi :

$id = searchForId('100', $userdb);

Il est important de savoir que si vous utilisez === Les types comparés doivent être exactement les mêmes, dans cet exemple vous devez rechercher string ou utiliser simplement == au lieu de === .

Sur la base de angoru répondre. Dans les versions ultérieures de PHP ( >= 5.5.0 ), vous pouvez utiliser la fonction "one-liner".

$key = array_search('100', array_column($userdb, 'uid'));

Voici la documentation : http://php.net/manual/en/function.array-column.php .

18 votes

Vous devriez également être capable de faire cela sans PHP 5.5 en utilisant array_map à la place de array_column. Remplacez simplement array_column($userdb, 'uid') con array_map(function($v){return $v['uid'];},$userdb)

2 votes

Oui, vous avez raison. Les fonctions lambda sont disponibles depuis PHP 5.3. et mieux encore, c'est array_search n'est-ce pas ?

4 votes

@angoru Je pense que la solution originale (le foreach ) sera plus rapide car elle s'arrête dès qu'une correspondance est trouvée. La solution la plus récente doit itérer sur l'ensemble du tableau une fois pour extraire array_column puis le parcourt en boucle une deuxième fois pour effectuer la recherche (jusqu'à ce qu'il trouve une correspondance). La nouvelle solution est plus facile à lire et plus concise, mais l'OP a spécifiquement soulevé le problème des performances

477voto

angoru Points 773

Si vous utilisez (PHP 5 >= 5.5.0) vous n'avez pas besoin d'écrire votre propre fonction pour faire cela, écrivez juste cette ligne et c'est fait.

Si vous ne voulez qu'un seul résultat :

$key = array_search(40489, array_column($userdb, 'uid'));

Pour des résultats multiples

$keys = array_keys(array_column($userdb, 'uid'), 40489);

Si vous avez un tableau associatif comme indiqué dans les commentaires, vous pouvez le faire avec :

$keys = array_keys(array_combine(array_keys($userdb), array_column($userdb, 'uid')),40489);

Si vous utilisez PHP < 5.5.0, vous pouvez utiliser ce backport Merci Ramsey !

Mise à jour : J'ai fait quelques tests simples et le formulaire de résultats multiples semble être le plus rapide, même plus rapide que la fonction personnalisée de Jakub !

0 votes

Que faire si la valeur que je recherche (dans cet exemple, 40489) apparaît plus d'une fois et que je veux obtenir toutes les clés où elle apparaît ?

0 votes

Si la valeur 40489 apparaît plus d'une fois dans le tableau, la fonction retournera-t-elle un tableau de clés ? @angoru

0 votes

Si vous utilisez le deuxième cas pour des résultats multiples, vous obtenez un tableau de clés.

33voto

reflexiv Points 804

En s'inspirant de l'expérience de Jakub excellente réponse Voici une recherche plus générale qui permet de spécifier la clé (et pas seulement l'uid) :

function searcharray($value, $key, $array) {
   foreach ($array as $k => $val) {
       if ($val[$key] == $value) {
           return $k;
       }
   }
   return null;
}

Utilisation : $results = searcharray('searchvalue', searchkey, $array);

1 votes

C'est très utile, j'ai l'impression d'être sur le point de résoudre mon problème en utilisant cette solution mais j'ai encore des problèmes. Pourriez-vous m'éclairer ? La question se trouve ici : stackoverflow.com/questions/28704644/

22voto

amurrell Points 348

Je sais que la réponse a déjà été donnée, mais j'ai utilisé cette méthode et je l'ai étendue un peu plus dans mon code pour que vous n'ayez pas à faire une recherche uniquement par l'uid. Je veux juste le partager pour tous ceux qui pourraient avoir besoin de cette fonctionnalité.

Voici mon exemple et n'oubliez pas qu'il s'agit de ma première réponse. J'ai supprimé le tableau param parce que je n'avais besoin de rechercher qu'un tableau spécifique, mais vous pourriez facilement l'ajouter. Je voulais essentiellement faire une recherche sur plus que l'uid.

De plus, dans mon cas, il peut y avoir plusieurs clés à renvoyer à la suite d'une recherche sur d'autres champs qui peuvent ne pas être uniques.

 /**
     * @param array multidimensional 
     * @param string value to search for, ie a specific field name like name_first
     * @param string associative key to find it in, ie field_name
     * 
     * @return array keys.
     */
     function search_revisions($dataArray, $search_value, $key_to_search) {
        // This function will search the revisions for a certain value
        // related to the associative key you are looking for.
        $keys = array();
        foreach ($dataArray as $key => $cur_value) {
            if ($cur_value[$key_to_search] == $search_value) {
                $keys[] = $key;
            }
        }
        return $keys;
    }

Plus tard, j'ai fini par écrire ceci pour me permettre de rechercher une autre valeur et une clé associative. Mon premier exemple vous permet donc de rechercher une valeur dans une clé associative spécifique et de renvoyer toutes les correspondances.

Ce deuxième exemple montre où se trouve une valeur ("Taylor") dans une certaine clé associative (first_name). ET une autre valeur (true) est trouvée dans une autre clé associative (employed), et renvoie toutes les correspondances (clés dans lesquelles les personnes dont le prénom est 'Taylor' ET sont employées).

/**
 * @param array multidimensional 
 * @param string $search_value The value to search for, ie a specific 'Taylor'
 * @param string $key_to_search The associative key to find it in, ie first_name
 * @param string $other_matching_key The associative key to find in the matches for employed
 * @param string $other_matching_value The value to find in that matching associative key, ie true
 * 
 * @return array keys, ie all the people with the first name 'Taylor' that are employed.
 */
 function search_revisions($dataArray, $search_value, $key_to_search, $other_matching_value = null, $other_matching_key = null) {
    // This function will search the revisions for a certain value
    // related to the associative key you are looking for.
    $keys = array();
    foreach ($dataArray as $key => $cur_value) {
        if ($cur_value[$key_to_search] == $search_value) {
            if (isset($other_matching_key) && isset($other_matching_value)) {
                if ($cur_value[$other_matching_key] == $other_matching_value) {
                    $keys[] = $key;
                }
            } else {
                // I must keep in mind that some searches may have multiple
                // matches and others would not, so leave it open with no continues.
                $keys[] = $key;
            }
        }
    }
    return $keys;
}

Utilisation de la fonction

$data = array(
    array(
        'cust_group' => 6,
        'price' => 13.21,
        'price_qty' => 5
    ),
    array(
        'cust_group' => 8,
        'price' => 15.25,
        'price_qty' => 4
    ),
    array(
        'cust_group' => 8,
        'price' => 12.75,
        'price_qty' => 10
    )
);

$findKey = search_revisions($data,'8', 'cust_group', '10', 'price_qty');
print_r($findKey);

Résultat

Array ( [0] => 2 )

10voto

voodoo417 Points 3931

J'ai modifié l'un des exemples ci-dessous en fonction de la description array_search . Fonction searchItemsByKey renvoie toutes les valeurs de $key dans un tableau multidimensionnel (N niveaux). Peut-être que cela pourrait être utile à quelqu'un. Exemple :

 $arr = array(
     'XXX'=>array(
               'YYY'=> array(
                    'AAA'=> array(
                          'keyN' =>'value1'
                   )
               ),
              'ZZZ'=> array(
                    'BBB'=> array(
                          'keyN' => 'value2'
                   )
               )
              //.....
           )
);

$result = searchItemsByKey($arr,'keyN');

print '<pre>';
print_r($result);
print '<pre>';
// OUTPUT
Array
(
  [0] => value1
  [1] => value2
)

Code de fonction :

function searchItemsByKey($array, $key)
{
   $results = array();

  if (is_array($array))
  {
    if (isset($array[$key]) && key($array)==$key)
        $results[] = $array[$key];

    foreach ($array as $sub_array)
        $results = array_merge($results, searchItemsByKey($sub_array, $key));
  }

 return  $results;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X