PHP Multidimensional Array Searching (zoeksleutel op specifieke waarde)

Ik heb deze multidimensionale array. Ik moet het zoeken en alleen de sleutel retourneren die overeenkomt met de waarde van de "slug". Ik weet dat er andere discussies zijn over het zoeken naar multidimensionale arrays, maar ik begrijp niet echt genoeg om op mijn situatie van toepassing te zijn. Heel erg bedankt voor alle hulp!

Dus ik heb een functie nodig zoals:

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

Hier is de Array:

$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'    => '',
        ),
);
73

8 antwoord

Erg makkelijk:

function myfunction($products, $field, $value)
{
   foreach($products as $key => $product)
   {
      if ( $product[$field] === $value )
         return $key;
   }
   return false;
}
117
toegevoegd
Als u deze functie gebruikt in een voorwaardelijke instructie, wilt u een absolute controle uitvoeren tegen het type, omdat de geretourneerde sleutel soms een index van [0] kan hebben. Dus als u een voorwaardelijke controle uitvoert, ziet het er ongeveer zo uit: if (myfunction ($ array, 'field', 'value')! == FALSE))//do something ...
toegevoegd de auteur Andy Cook, de bron

Een andere bruikbare oplossing is gebaseerd op de functie array_search() . U moet PHP 5.5.0 of hoger gebruiken.

Voorbeeld

$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

Uitleg

De functie array_search() heeft twee argumenten. De eerste is de waarde die u wilt doorzoeken. De tweede is waar de functie moet zoeken. De functie array_column() krijgt de waarden van de elementen welke sleutel 'uid' is.

Samenvatting

Dus je zou het kunnen gebruiken als:

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

of, als je wilt:

// 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 Voorbeeld(by xfoxawy) can be found on the DOCS.
The array_column() page.


Bijwerken

Vanwege de commentaar van Vael was ik nieuwsgierig, dus heb ik een eenvoudige test gemaakt om de prestaties te bepalen van de methode die array_search gebruikt en de voorgestelde methode voor het geaccepteerde antwoord.

Ik heb een array gemaakt met 1000 arrays, de structuur was als volgt (alle gegevens waren willekeurig):

[
      {
            "_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 Voorbeeld.

De resultaten waren dat de methode die op dit antwoord werd voorgesteld ongeveer 2E-7 nodig had om de waarde te vinden, terwijl de geaccepteerde antwoordmethode ongeveer 8E-7 nodig had.

Zoals ik al eerder zei, beide keren zijn vrij acceptabel voor een toepassing die een array met deze grootte gebruikt. Als de grootte veel groeit, laten we zeggen 1 miljoen elementen, dan zal dit kleine verschil ook worden verhoogd.

Update II

Ik heb een test toegevoegd voor de methode op basis van array_walk_recursive , die op enkele van de antwoorden hier vermeld stond. Het resultaat is de juiste. En als we ons concentreren op de uitvoering, is deze iets slechter dan de andere die zijn onderzocht in de test . In de test kunt u zien dat dit ongeveer 10 keer langzamer is dan de methode op basis van array_search . Nogmaals, dit is niet een heel relevant verschil voor de meeste toepassingen.

Update III

Met dank aan @mickmackusa voor het vinden van verschillende beperkingen op deze methode:

  • Deze methode zal mislukken op associatieve sleutels.
  • Deze methode werkt alleen op geïndexeerde subarrays (beginnend bij 0 en met opeenvolgende oplopende toetsen).
80
toegevoegd
Weet iemand de uitvoering hiervan? Het lijkt erop dat het uiteindelijk langzamer zou zijn en toch 5.5 zou vereisen. Ik kan niet testen als ik 5.4 gebruik.
toegevoegd de auteur Vael Victus, de bron
Voor iedereen die het niet begrijpt: in PHP 7 zijn de for-loops sneller. Toen ik in die eval.in bijvoorbeeld veranderde naar 5.6, was array_search iets sneller.
toegevoegd de auteur Vael Victus, de bron
Het gebruik van array_search() met array_column() werkt niet op de samplearray van OP, omdat de subarray-sleutels beginnen met 1 . Deze methode mislukt ook op associatieve sleutels. Deze methode werkt alleen op geïndexeerde subarrays (beginnend met 0 en met opeenvolgende oplopende toetsen). De reden hiervoor is dat array_column() nieuwe indexen genereert in de geretourneerde array.
toegevoegd de auteur mickmackusa, de bron
Het werkt! Bedankt maan $ key = array_search (40489, array_column ($ userdb, 'uid'));
toegevoegd de auteur tthreetorch, de bron
helemaal gelijk @mickmackusa, ik heb je kennis toegevoegd aan het antwoord. Bedankt voor de hulp
toegevoegd de auteur Iván Rodríguez Torre, de bron
slim! Ik deed iets vergelijkbaars, met array_combine() met array_column() om een ​​andere array te maken om mijn datum te pakken met een bekende sleutel, maar dit is eleganter.
toegevoegd de auteur David, de bron

Deze klassemethode kan in array zoeken op meerdere voorwaarden:

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

Zal produceren:

array(2) {
  [5]=>
  array(2) {
    ["foo"]=>
    string(5) "test4"
    ["bar"]=>
    string(4) "baz1"
  }
  [10]=>
  array(2) {
    ["foo"]=>
    string(5) "test4"
    ["bar"]=>
    string(4) "baz1"
  }
}
11
toegevoegd
Hallo Fatalist stackoverflow.com/questions/40860030/… . Het is toegevoegd aan deze vraag. Kunt u deze vraag alstublieft verduidelijken?
toegevoegd de auteur KARTHI SRV, de bron
Uw oplossing heeft geholpen met mijn probleem ..
toegevoegd de auteur technology_dreamer, de bron

Gebruik deze functie:

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;
}

}

en belfunctie.

print_r(searchThroughArray('breville-one-touch-tea-maker-BTM800XL',$products));
2
toegevoegd
Alleen code-antwoorden zijn laag in StackOverflow. Werk uw bericht bij om uit te leggen hoe uw bladknooppunt-substring-zoekfunctie werkt. Deze methode is niet specifiek ontworpen om te werken zoals het OP vraagt, dus het is belangrijk om de verschillen te verduidelijken. Een demolink zou het begrip van de lezer aanzienlijk verbeteren. Plaats altijd antwoorden met de bedoeling om het OP en het grotere SO-publiek op te voeden.
toegevoegd de auteur mickmackusa, de bron
Goed antwoord. U kunt de prestaties van uw voorstel controleren op mijn antwoord
toegevoegd de auteur Iván Rodríguez Torre, de bron

Voor de volgende bezoeker die langskomt: gebruik de recursieve array-wandeling; het bezoekt elk "blad" in de multidimensionale array. Dit is voor inspiratie:

function getMDArrayValueByKey($a, $k) {
    $r = [];
    array_walk_recursive ($a, 
                          function ($item, $key) use ($k, &$r) {if ($key == $k) $r[] = $item;}
                          );
    return $r;
}
1
toegevoegd
@Ivan josef's antwoord is heel anders dan deze. Heb je dit zelf getest? Ik blijf dit antwoord in de gaten houden en ik denk niet dat het kan werken omdat array_walk_recursive geen niveau kan zien. Voor elke eerste niveausleutel belt josef strpos of controleert hij alle leafknooppunten. Zie het verschil?
toegevoegd de auteur mickmackusa, de bron
Geen probleem! gewoon om u tijd te besparen, als u het antwoord van Joseph probeert, retourneert de functie een array met één element. De sleutel is het gewenste antwoord :)
toegevoegd de auteur Iván Rodríguez Torre, de bron
Natuurlijk @mickmackusa Maar Hans geeft een soort van inspiratie, het antwoord geeft de oplossing niet letterlijk. Het heeft meer uitwerking nodig, zoals Josef deed op zijn antwoord. Maar u hebt gelijk in het punt dat dit antwoord het probleem niet volledig aanpakt.
toegevoegd de auteur Iván Rodríguez Torre, de bron
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
toegevoegd
Alleen code-antwoorden zijn laag in StackOverflow. Werk uw bericht bij om uit te leggen hoe uw recursieve methode werkt, de situaties waarin deze geschikt is en situaties waarin recursie overbodig is. Plaats altijd antwoorden met de bedoeling om het OP en het grotere SO-publiek op te voeden.
toegevoegd de auteur mickmackusa, de bron

Probeer dit

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
toegevoegd
Alleen code-antwoorden zijn laag in StackOverflow. Werk uw bericht bij om uit te leggen hoe uw recursieve methode werkt, de situaties waarin deze geschikt is en situaties waarin recursie overbodig is. Plaats altijd antwoorden met de bedoeling om het OP en het grotere SO-publiek op te voeden. Postscriptum Ik denk dat de meeste php-ontwikkelaars de voorkeur geven aan && en || in plaats van AND en OF in uw situatie. Er is geen reden om current_key te declareren. De vergelijking op $ needle moet strikt zijn.
toegevoegd de auteur mickmackusa, de bron

Ik zou het hieronder willen doen, waarbij $ producten de werkelijke reeks is die in het begin bij het probleem is gegeven.

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

0
toegevoegd