web-dev-qa-db-fra.com

PHP Recherche multidimensionnelle sur un tableau (Recherche d'une clé par une valeur spécifique)

J'ai ce tableau multidimensionnel. Je dois le rechercher et ne renvoyer que la clé qui correspond à la valeur du "slug". Je sais que la recherche de tableaux multidimensionnels comporte d'autres éléments, mais je ne suis pas assez compréhensive pour l'appliquer à ma situation. Merci beaucoup pour toute aide!

J'ai donc besoin d'une fonction comme:

myfunction($products,'breville-one-touch-tea-maker-BTM800XL');
// returns 1

Voici le tableau:

$products = array (
1  => array(
        'name'          => 'The Breville One-Touch Tea Maker',
        'slug'          => 'breville-one-touch-tea-maker-BTM800XL',
        'shortname'     => 'The One-Touch Tea Maker',
        'listprice'     => '299.99',
        'price'         => '249.99',
        'rating'        => '9.5',
        'reviews'       => '81',
        'buyurl'        => 'http://www.Amazon.com/The-Breville-One-Touch-Tea-Maker/dp/B003LNOPSG',
        'videoref1'     => 'xNb-FOTJY1c',
        'videoref2'     => 'WAyk-O2B6F8',
        'image'         => '812BpgHhjBML.jpg',
        'related1'      => '2',
        'related2'      => '3',
        'related3'      => '4',
        'bestbuy'       => '1',
        'quote'         => '',
        'quoteautor'    => 'K. Martino',
        ),

2  => array(
        'name'          => 'Breville Variable-Temperature Kettle BKE820XL',
        'slug'          => 'breville-variable-temperature-kettle-BKE820XL',
        'shortname'     => 'Variable Temperature Kettle',
        'listprice'     => '199.99',
        'price'         => '129.99',
        'rating'        => '9',
        'reviews'       => '78',
        'buyurl'        => 'http://www.Amazon.com/Breville-BKE820XL-Variable-Temperature-1-8-Liter-Kettle/dp/B001DYERBK',
        'videoref1'     => 'oyZWBD83xeE',
        'image'         => '41y2B8jSKmwL.jpg',
        'related1'      => '3',
        'related2'      => '4',
        'related3'      => '5',
        'bestbuy'       => '1',
        'quote'         => '',
        'quoteautor'    => '',
        ),
);
87
Ben Kouba

Très simple:

function myfunction($products, $field, $value)
{
   foreach($products as $key => $product)
   {
      if ( $product[$field] === $value )
         return $key;
   }
   return false;
}
134
Aurelio De Rosa

Une autre solution possible est basée sur la fonction array_search(). Vous devez utiliser PHP 5.5.0 ou supérieur. 

Exemple

$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

Explication

La fonction array_search() a deux arguments. Le premier est la valeur que vous souhaitez rechercher. La seconde est l'endroit où la fonction devrait chercher. La fonction array_column() récupère les valeurs des éléments dont la clé est 'uid'.

Résumé

Pour que vous puissiez l'utiliser comme:

array_search('breville-one-touch-tea-maker-BTM800XL', array_column($products, 'slug'));

ou, si vous préférez:

// 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');

L'exemple original (par xfoxawy) se trouve sur le DOCS .
Le array_column()page .


Mettre à jour

En raison du commentaire de Vael, j’étais curieux et j’ai donc fait un test simple pour mesurer les performances de la méthode qui utilise array_search et celle proposée sur la réponse acceptée. 

J'ai créé un tableau contenant 1000 tableaux, la structure était la suivante (toutes les données étaient randomisées):

[
      {
            "_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"
      },...
]

J'ai exécuté le test de recherche 100 fois en recherchant différentes valeurs pour le champ de nom, puis j'ai calculé le temps moyen dans millisecondes. _ { Here } _ vous pouvez voir un exemple.

Les résultats ont montré que la méthode proposée pour cette réponse nécessitait environ 2E-7 pour trouver la valeur, tandis que la méthode de réponse acceptée nécessitait environ 8E-7.

Comme je l'ai déjà dit, les temps sont assez acceptables pour une application utilisant un tableau de cette taille. Si la taille augmente beaucoup, disons des éléments 1M, alors cette petite différence sera augmentée aussi. 

Mise à jour II

J'ai ajouté un test pour la méthode basée sur array_walk_recursive qui a été mentionné sur certaines des réponses ici. Le résultat obtenu est le bon. Et si nous nous concentrons sur les performances, c'est un peu pire que les autres examinées sur le test . Dans le test, vous pouvez constater qu’il est environ 10 fois plus lent que la méthode basée sur array_search. Encore une fois, cette différence n’est pas très pertinente pour la plupart des applications. 

Mise à jour III

Merci à @mickmackusa pour avoir relevé plusieurs limitations sur cette méthode:

  • Cette méthode échouera sur les clés associatives. 
  • Cette méthode ne fonctionnera que sur les sous-tableaux indexés (à partir de 0 et ayant des clés ascendantes consécutives).
99

Cette méthode de classe peut rechercher dans un tableau selon plusieurs conditions:

class Stdlib_Array
{
    public static function multiSearch(array $array, array $pairs)
    {
        $found = array();
        foreach ($array as $aKey => $aVal) {
            $coincidences = 0;
            foreach ($pairs as $pKey => $pVal) {
                if (array_key_exists($pKey, $aVal) && $aVal[$pKey] == $pVal) {
                    $coincidences++;
                }
            }
            if ($coincidences == count($pairs)) {
                $found[$aKey] = $aVal;
            }
        }

        return $found;
    }    
}

// Example:

$data = array(
    array('foo' => 'test4', 'bar' => 'baz'),
    array('foo' => 'test',  'bar' => 'baz'),
    array('foo' => 'test1', 'bar' => 'baz3'),
    array('foo' => 'test',  'bar' => 'baz'),
    array('foo' => 'test',  'bar' => 'baz4'),
    array('foo' => 'test4', 'bar' => 'baz1'),
    array('foo' => 'test',  'bar' => 'baz1'),
    array('foo' => 'test3', 'bar' => 'baz2'),
    array('foo' => 'test',  'bar' => 'baz'),
    array('foo' => 'test',  'bar' => 'baz'),
    array('foo' => 'test4', 'bar' => 'baz1')
);

$result = Stdlib_Array::multiSearch($data, array('foo' => 'test4', 'bar' => 'baz1'));

var_dump($result);

Produira:

array(2) {
  [5]=>
  array(2) {
    ["foo"]=>
    string(5) "test4"
    ["bar"]=>
    string(4) "baz1"
  }
  [10]=>
  array(2) {
    ["foo"]=>
    string(5) "test4"
    ["bar"]=>
    string(4) "baz1"
  }
}
12
Fatalist

Utilisez cette fonction:

function searchThroughArray($search,array $lists){
try{
    foreach ($lists as $key => $value) {
        if(is_array($value)){
            array_walk_recursive($value, function($v, $k) use($search ,$key,$value,&$val){
                if(strpos($v, $search) !== false )  $val[$key]=$value;
            });
    }else{
            if(strpos($value, $search) !== false )  $val[$key]=$value;
        }

    }
    return $val;

}catch (Exception $e) {
    return false;
}

}

et appelez la fonction.

print_r(searchThroughArray('breville-one-touch-tea-maker-BTM800XL',$products));
4
josef

Pour le prochain visiteur qui arrive: utilisez la promenade de tableau récursive; il visite toutes les "feuilles" du tableau multidimensionnel. Voici pour l'inspiration:

function getMDArrayValueByKey($a, $k) {
    $r = [];
    array_walk_recursive ($a, 
                          function ($item, $key) use ($k, &$r) {if ($key == $k) $r[] = $item;}
                          );
    return $r;
}
1
Hans
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; 
} 
1
mikelee

Essaye ça

function recursive_array_search($needle,$haystack) {
        foreach($haystack as $key=>$value) {
            $current_key=$key;
            if($needle==$value['uid'] OR (is_array($value) && recursive_array_search($needle,$value) !== false)) {
                return $current_key;
            }
        }
        return false;
    }
0
pawan sen

Je voudrais faire comme ci-dessous, où $products est le tableau réel donné dans le problème au tout début.

print_r(
  array_search("breville-variable-temperature-kettle-BKE820XL", 
  array_map(function($product){return $product["slug"];},$products))
);
0
Sam Kaz