2012-12-17 3 views
7

Tôi có một danh sách mảng (ví dụ này tôi đang sử dụng điện thoại di động). Tôi muốn có thể tìm kiếm nhiều cặp khóa/giá trị và trả về chỉ mục mảng chính của nó.PHP Tìm kiếm một mảng cho nhiều cặp khóa/giá trị

Ví dụ, đây là mảng của tôi:

// $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 
     ) 
) 

Tôi muốn để có thể làm điều gì đó như sau:

// 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. 

Bất kỳ ý tưởng hoặc đề xuất về làm thế nào tôi có thể hoặc nên làm cái này?

+0

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

+0

Bạn đã chỉ cho tôi đúng hướng, và tôi đã tìm ra nó từ đó. Đôi khi bạn chỉ cần suy nghĩ của người ngoài cuộc! Cảm ơn –

Trả lời

9

Có lẽ đây sẽ hữu ích:

/** 
    * 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 () 

Như các chương trình đầu ra, chức năng này sẽ trả về một mảng của tất cả các phím với các yếu tố đáp ứng tất cả các tiêu chí tìm kiếm.

+0

Chức năng đẹp, nó hoạt động như mô tả. 'Foreach' thứ hai về cơ bản thực hiện những gì' mảng_search' thực hiện trong đoạn mã của tôi ở trên. Vì bạn là câu trả lời thực sự duy nhất cho đến giờ, và nó hoạt động, tôi sẽ đánh dấu câu trả lời của bạn là câu trả lời được chấp nhận. Cảm ơn vì bạn đã phản hồi! –

+1

'mảng_search' không giống hệt nhau. Nó không kiểm tra các khóa, chỉ các giá trị, vì vậy nó không kiểm tra xem liệu 'Nhà sản xuất' có phải là' Apple' hay không, chỉ khi 'Apple' nằm trong mảng ở đâu đó (chúng có thể trở thành một nhà cung cấp dịch vụ tại một số điểm) . – MichaelRushton

+0

Giải pháp này phải được chấp nhận. Chỉ một vấn đề: nếu một số mảng chứa 'NULL' (ví dụ: '[' Nhà sản xuất '=>' Motorola ',' Mẫu '=> NULL]'), điều kiện 'if (! Isset ($ value [$ k]) || $ value [$ k]! = $ v) 'sẽ không kích hoạt. Vì vậy, tôi đề xuất thay đổi điều kiện đó: 'if ((! Isset ($ value [$ k]) && $ value [$ k]! == null) || $ value [$ k]! = $ V)'. –

5

bạn có thể sử dụng array_intersect_key và array_intersect và array_search

séc array_intersect_key php manual để có được hàng loạt các mục có phù hợp với phím

array_intesect php manual để có được mảng nếu mục có phù hợp với các giá trị

u có thể nhận được giá trị của key trong mảng sử dụng $array[key]

và nhận khóa giá trị trong mảng sử dụng array_search $key = array_search('green', $array);

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

+0

Tôi đã kết thúc lặp qua '$ list_of_phones' với vòng lặp foreach, sau đó array_searching mỗi kết quả cho các giá trị. Nó hoạt động, nhưng trông vẫn bị hack. Nếu bạn có thể giải thích phương pháp của bạn sâu hơn một chút, tôi sẽ thử. –

3

Tôi đã thực hiện các bước sau. Nó không đẹp, nhưng hoạt động rất tốt. Đối với bất kỳ ai đọc, vui lòng cập nhật bằng câu trả lời DRYer:

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

Hoạt động như một sự quyến rũ.

+1

Thật ngạc nhiên, phương pháp này thực sự nhanh gấp 5 lần câu trả lời được chấp nhận. Cấp nó là một mảng nhỏ, nhưng sự khác biệt là đáng kể. Đây là một câu đố. http://www.tehplayground.com/#du9XzNFqs – MikelG

0

Bằng cách này làm việc cho một mảng multidimensinal như của bạn:

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

tôi mở rộng @ đang MichaelRushton bằng cách thêm hỗ trợ cho toán tử so sánh khác nhau:

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

Đây là giống như @Boolean_Type nhưng nâng cao một chút để đơn giản hóa mọi thứ.

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

Bằng cách này, bạn chỉ có thể tìm kiếm như thế này:

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

Nếu tìm thấy, bạn sẽ có và hàng loạt các chỉ số như sau: array(1, 25, 33) (Đây chỉ là một ví dụ).