2012-12-17 9 views
7

Mam listę tablic (w tym przykładzie używam telefonów komórkowych). Chcę mieć możliwość wyszukania wielu par klucz/wartość i zwrócenia jej indeksu tablicy nadrzędnej.PHP Wyszukaj tablicę dla wielu par klucz/wartość

Na przykład, tutaj jest moja tablica:

// $list_of_phones (array) 
Array 
(
    [0] => Array 
     (
      [Manufacturer] => Apple 
      [Model] => iPhone 3G 8GB 
      [Carrier] => AT&T 
     ) 

    [1] => Array 
     (
      [Manufacturer] => Motorola 
      [Model] => Droid X2 
      [Carrier] => Verizon 
     ) 
) 

ja chce być w stanie coś zrobić tak:

// This is not a real function, just used for example purposes 
$phone_id = multi_array_search(array('Manufacturer' => 'Motorola', 'Model' => 'Droid X2'), $list_of_phones); 

// $phone_id should return '1', as this is the index of the result. 

jakieś pomysły lub sugestie, w jaki sposób ja może lub powinna Zrób to?

+0

['foreach'] (http://php.net/foreach)? – Charles

+0

Wskazałaś mi właściwy kierunek, a ja to odkryłem. Czasami potrzebujesz myśli outsidera! Dzięki –

Odpowiedz

9

Może to być przydatne:

/** 
    * Multi-array search 
    * 
    * @param array $array 
    * @param array $search 
    * @return array 
    */ 
    function multi_array_search($array, $search) 
    { 

    // Create the result array 
    $result = array(); 

    // Iterate over each array element 
    foreach ($array as $key => $value) 
    { 

     // Iterate over each search condition 
     foreach ($search as $k => $v) 
     { 

     // If the array element does not meet the search condition then continue to the next element 
     if (!isset($value[$k]) || $value[$k] != $v) 
     { 
      continue 2; 
     } 

     } 

     // Add the array element's key to the result array 
     $result[] = $key; 

    } 

    // Return the result array 
    return $result; 

    } 

    // Output the result 
    print_r(multi_array_search($list_of_phones, array())); 

    // Array ([0] => 0 [1] => 1) 

    // Output the result 
    print_r(multi_array_search($list_of_phones, array('Manufacturer' => 'Apple'))); 

    // Array ([0] => 0) 

    // Output the result 
    print_r(multi_array_search($list_of_phones, array('Manufacturer' => 'Apple', 'Model' => 'iPhone 6'))); 

    // Array () 

Jak widać wyjściowych, to funkcja zwraca tablicę wszystkich kluczy z elementów, które spełniają wszystkie kryteria wyszukiwania.

+0

Dobra funkcja, działa zgodnie z opisem. Drugie "foreach" w zasadzie robi to, co "array_search" w moim zbuforowanym kawałku kodu powyżej. Ponieważ do tej pory jesteś jedyną prawdziwą odpowiedzią i to działa, zaznaczę twoją odpowiedź jako zaakceptowaną. Dzięki za opinie! –

+1

'array_search' nie jest dokładnie taki sam. Nie sprawdza kluczy, tylko wartości, więc nie sprawdza, czy 'Producent' jest' Apple', tylko jeśli 'Apple' jest gdzieś w tablicy (mogą stać się nośnikiem w pewnym momencie) . – MichaelRushton

+0

To rozwiązanie powinno zostać zaakceptowane. Tylko jeden problem: jeśli niektóre tablice zawierają 'NULL' (na przykład:' ['Producent' => 'Motorola', 'Model' => NULL] '), warunek' if (! Isset ($ value [$ k]) || wartość $ [$ k]! = $ v) 'nie uruchomi się. Proponuję zmienić ten warunek: 'if ((! Isset ($ value [$ k]) && $ value [$ k]! == null) || $ value [$ k]! = $ V)'. –

5

można użyć array_intersect_key i array_intersect i array_search

check array_intersect_key php manual dostać tablicę elementów z pasującymi kluczami

i array_intesect php manual dostać tablicę jeśli elementy z odpowiadających sobie wartości

u można uzyskać wartość klucza w tablicy używającej $array[key]

i pobierz klucz wartości w tablicy przy użyciu array_search $key = array_search('green', $array);

php.net/manual/en/function.array-search.php

+0

zakończyłem pętlę '$ list_of_phones' z pętlą foreach, a następnie array_searching każdy wynik dla wartości. Działa, ale nadal wygląda na zhakowaną. Jeśli potrafisz wyjaśnić swoją metodę nieco głębiej, spróbuję. –

3

W rezultacie wykonałem następujące czynności. Nie jest ładny, ale działa bardzo dobrze. Dla każdego, kto czyta, nie krępuj się aktualizować z odpowiedzią Suszarka:

// Variables for this example 
$carrier = 'Verizon'; 
$model = 'Droid X2'; 
$manufacturer = 'Motorola'; 

// The foreach loop goes through each key/value of $list_of_phones and checks 
// if the given value is found in that particular array. If it is, it then checks 
// a second parameter (model), and so on. 
foreach ($list_of_phones as $key => $object) 
{ 
    if (array_search($carrier, $object)) 
    { 
     if (array_search($model, $object)) 
     { 
      if (array_search($manufacturer, $object)) 
      { 
       // Return the phone from the $list_of_phones array 
       $phone = $list_of_phones[$key]; 
      } 
     } 
    } 
} 

działa jak czar.

+1

Ku mojemu zdziwieniu, ta metoda jest 5 razy szybsza od zaakceptowanej odpowiedzi. To prawda, że ​​to mała tablica, ale różnica jest znacząca. Oto skrzypce. http://www.tehplayground.com/#du9XzNFqs – MikelG

0

ten sposób działa na multidimensinal tablicy jak Twoja:

$test = array_intersect_key($list_of_phones, array(array("Manufacturer" => "Motorola", "Carrier" => "Verizon"))); 
0

I rozszerzonym @ kodu MichaelRushton dodając wsparcie dla różnych operatorów porównania:

function multi_array_search ($array, $search) { 
    $result = []; 

    foreach ($array as $key => $value) { //iterate over each array element 
     foreach ($search as $k => $v) { //iterate over each search condition 
      $operator = $v[0]; 
      $searchField = $v[1]; 
      $searchVal = $v[2]; 

      switch ($operator) { 
       case '=': 
        $cond = ($value[$searchField] != $searchVal); 
        break; 

       case '!=': 
        $cond = ($value[$searchField] == $searchVal); 
        break; 

       case '>': 
        $cond = ($value[$searchField] <= $searchVal); 
        break; 

       case '<': 
        $cond = ($value[$searchField] >= $searchVal); 
        break; 

       case '>=': 
        $cond = ($value[$searchField] < $searchVal); 
        break; 

       case '<=': 
        $cond = ($value[$searchField] > $searchVal); 
        break; 
      } 

      //if the array element does not meet the search condition then continue to the next element 
      if ((!isset($value[$searchField]) && $value[$searchField] !== null) || $cond) { 
       continue 2; 
      } 
     } 
     $result[] = $key; //add the array element's key to the result array 
    } 
    return $result; 
} 

    //incoming data: 
    $phonesList = [ 
     0 => [ 
      'Manufacturer' => 'Apple', 
      'Model' => 'iPhone 3G 8GB', 
      'Carrier' => 'AT&T', 
      'Cost' => 100000 
     ], 
     1 => [ 
      'Manufacturer' => 'Motorola', 
      'Model' => 'Droid X2', 
      'Carrier' => 'Verizon', 
      'Cost' => 120000 
     ], 
     2 => [ 
      'Manufacturer' => 'Motorola', 
      'Model' => 'Droid X2', 
      'Carrier' => 'Verizon', 
      'Cost' => 150000 
     ] 
    ]; 

    var_dump(multi_array_search($phonesList, 
          [ ['=', 'Manufacturer', 'Motorola'], 
           ['>', 'Cost', '130000'] ] 
      )); 

    //output: 
    array(1) { [0]=> int(2) } 
0

To jest taka sama jak @Boolean_Type jednak wzmocniona trochę, aby uprościć rzeczy.

function multi_array_search($array, $search) 
{ 
    $result = array(); 

    foreach ($array as $key => $val) 
    { 
     foreach ($search as $k => $v) 
     { 
      // We check if the $k has an operator. 
      $operator = '='; 
      if (preg_match('(<|<=|>|>=|!=|=)', $k, $m) === 1) 
      { 
       // We change the operator. 
       $operator = $m[0]; 

       // We trim $k to remove white spaces before and after. 
       $k = trim(str_replace($m[0], '', $k)); 
      } 

      switch ($operator) 
      { 
       case '=': 
        $cond = ($val[$k] != $v); 
        break; 

       case '!=': 
        $cond = ($val[$k] == $v); 
        break; 

       case '>': 
        $cond = ($val[$k] <= $v); 
        break; 

       case '<': 
        $cond = ($val[$k] >= $v); 
        break; 

       case '>=': 
        $cond = ($val[$k] < $sv); 
        break; 

       case '<=': 
        $cond = ($val[$k] > $sv); 
        break; 
      } 

      if ((! isset($val[$k]) && $val[$k] !== null) OR $cond) 
      { 
       continue 2; 
      } 
     } 

     $result[] = $key; 
    } 

    return $result; 
} 

W ten sposób można łatwo przeszukiwać tak:

$keys = multi_array_search($phonesList, array(
    'Manufacturer' => 'Motorola', 
    'Cost >'  => '130000', 
)); 

przypadku stwierdzenia, trzeba będzie i tablica wskaźników tak: array(1, 25, 33) (Jest to tylko przykład).