Tìm kiếm mảng đa chiều trong PHP (Tìm khóa theo giá trị cụ thể)


114

Tôi có mảng đa chiều này. Tôi cần tìm kiếm nó và chỉ trả lại khóa khớp với giá trị của "slug". Tôi biết có nhiều chủ đề khác về tìm kiếm mảng đa chiều, nhưng tôi không thực sự hiểu đủ để áp dụng vào tình huống của mình. Cảm ơn rất nhiều sự giúp đỡ nào!

Vì vậy, tôi cần một chức năng như:

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

Đây là Mảng:

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

Câu trả lời:


157

Rất đơn giản:

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

6
Nếu bạn đang sử dụng hàm này trong một câu lệnh điều kiện, bạn sẽ muốn kiểm tra tuyệt đối kiểu vì khóa trả về đôi khi có thể có chỉ mục là [0]. Vì vậy, nếu làm một kiểm tra điều kiện, nó sẽ giống như thế này: if (myfunction($array, 'field', 'value') !== FALSE )) // do something...
Andy Cook

159

Một giải pháp khả thi khác là dựa trên array_search()chức năng. Bạn cần sử dụng PHP 5.5.0 trở lên.

Thí dụ

$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

Giải trình

Hàm array_search()có hai đối số. Giá trị đầu tiên là giá trị bạn muốn tìm kiếm. Thứ hai là nơi hàm nên tìm kiếm. Hàm array_column()nhận giá trị của các phần tử là khóa 'uid'.

Tóm lược

Vì vậy, bạn có thể sử dụng nó như:

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

hoặc, nếu bạn thích:

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

Ví dụ ban đầu (của xfoxawy) có thể được tìm thấy trên DOCS .
Các array_column() trang .


Cập nhật

Do nhận xét của Vael, tôi rất tò mò, vì vậy tôi đã thực hiện một bài kiểm tra đơn giản để đảm bảo hiệu suất của phương pháp sử dụng array_searchvà phương pháp được đề xuất trên câu trả lời được chấp nhận.

Tôi đã tạo một mảng chứa 1000 mảng, cấu trúc như thế này (tất cả dữ liệu được ngẫu nhiên hóa):

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

Tôi đã chạy thử nghiệm tìm kiếm 100 lần để tìm kiếm các giá trị khác nhau cho trường tên và sau đó tôi tính thời gian trung bình theo mili giây . Ở đây bạn có thể xem một ví dụ.

Kết quả là phương pháp được đề xuất trên câu trả lời này cần khoảng 2E-7 để tìm giá trị, trong khi phương pháp trả lời được chấp nhận cần khoảng 8E-7.

Như tôi đã nói trước đây, cả hai lần đều khá dễ chấp nhận đối với một ứng dụng sử dụng mảng với kích thước này. Nếu kích thước tăng lên nhiều, giả sử 1M phần tử, thì sự khác biệt nhỏ này cũng sẽ tăng lên.

Cập nhật II

Tôi đã thêm một thử nghiệm cho phương pháp dựa trên đó dựa array_walk_recursivetrên một số câu trả lời ở đây. Kết quả nhận được là một trong những chính xác. Và nếu chúng ta tập trung vào hiệu suất, nó sẽ kém hơn một chút so với những người khác đã kiểm tra trong bài kiểm tra . Trong thử nghiệm, bạn có thể thấy tốc độ đó chậm hơn khoảng 10 lần so với phương pháp dựa trên array_search. Một lần nữa, đây không phải là một sự khác biệt phù hợp cho hầu hết các ứng dụng.

Cập nhật III

Cảm ơn @mickmackusa vì đã phát hiện ra một số hạn chế trong phương pháp này:

  • Phương pháp này sẽ không thành công trên các khóa liên kết.
  • Phương thức này sẽ chỉ hoạt động trên các mảng con được lập chỉ mục (bắt đầu từ 0 và có các khóa tăng dần liên tục).

Có ai biết hiệu suất của điều này? Có vẻ như cuối cùng nó sẽ chậm hơn và vẫn yêu cầu 5.5. Tôi không thể kiểm tra khi tôi đang ở trên 5.4.
Vael Victus

Đối với bất kỳ ai không hiểu: trong php 7, vòng lặp for nhanh hơn. Khi tôi thay đổi thành 5.6 trong ví dụ eval.in đó, array_search nhanh hơn một chút.
Vael Victus

tài giỏi! Tôi đã làm một cái gì đó tương tự, sử dụng array_combine () với array_column () để tạo một mảng khác từ đó lấy dữ liệu của tôi với một khóa đã biết, nhưng điều này thanh lịch hơn.
David

4
Việc sử dụng array_search()với array_column()sẽ không hoạt động trên mảng mẫu của OP vì các khóa của mảng con bắt đầu từ đó 1. Phương pháp này cũng sẽ không thành công trên các khóa liên kết. Phương pháp này sẽ chỉ hoạt động trên các mảng con được lập chỉ mục (bắt đầu từ 0và có các khóa tăng dần liên tục). Lý do cho điều này là vì array_column()sẽ tạo ra các chỉ mục mới trong mảng được trả về của nó.
mickmackusa

hoàn toàn đúng @mickmackusa, tôi đã thêm kiến ​​thức của bạn vào câu trả lời. Cảm ơn sự giúp đỡ
Iván Rodríguez Torres

14

Phương thức lớp này có thể tìm kiếm trong mảng theo nhiều điều kiện:

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

Sẽ sản xuất:

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

Xin chào Fatalist stackoverflow.com/questions/40860030/… . Nó được releted những câu hỏi mà bạn có thể vui lòng làm rõ câu hỏi rằng
KARTHI SRV

4

Sử dụng chức năng này:

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

và chức năng gọi.

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

Câu trả lời rất hay. Bạn có thể kiểm tra việc thực hiện các đề xuất của bạn về câu trả lời của tôi
Iván Rodríguez Torres

Các câu trả lời chỉ có mã có giá trị thấp trên StackOverflow. Vui lòng cập nhật bài đăng của bạn để giải thích cách hoạt động của chức năng tìm kiếm chuỗi con nút lá của bạn. Phương pháp này không được thiết kế đặc biệt để hoạt động như yêu cầu của OP, vì vậy điều quan trọng là phải làm rõ sự khác biệt. Một liên kết demo sẽ cải thiện đáng kể khả năng hiểu của người đọc. Luôn đăng câu trả lời với mục đích giáo dục OP và những khán giả SO lớn hơn.
mickmackusa

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

Các câu trả lời chỉ có mã có giá trị thấp trên StackOverflow. Vui lòng cập nhật bài đăng của bạn để giải thích cách hoạt động của phương pháp đệ quy, các tình huống thích hợp và các tình huống mà đệ quy là chi phí không cần thiết. Luôn đăng câu trả lời với mục đích giáo dục OP và những khán giả SO lớn hơn.
mickmackusa

1

Đối với khách truy cập tiếp theo đến cùng: sử dụng lối đi mảng đệ quy; nó thăm mọi "lá" trong mảng đa chiều. Đây là nguồn cảm hứng:

function getMDArrayValueByKey($a, $k) {
    $r = [];
    array_walk_recursive ($a, 
                          function ($item, $key) use ($k, &$r) {if ($key == $k) $r[] = $item;}
                          );
    return $r;
}

Không vấn đề gì! chỉ để tiết kiệm thời gian cho bạn, nếu bạn thử josef answer, hàm sẽ trả về một mảng có một phần tử. Điều quan trọng là câu trả lời mong muốn :)
Iván Rodríguez Torres

Câu trả lời của @Ivan josef rất khác với câu trả lời này. Bạn đã kiểm tra điều này cho mình. Tôi tiếp tục chú ý đến câu trả lời này và tôi không nghĩ rằng nó có thể hoạt động vì array_walk_recursive không thể tăng cấp. Đối với mỗi khóa cấp đầu tiên, josef đang gọi strpos hoặc kiểm tra tất cả các lá. Thấy sự khác biệt?
mickmackusa

Tất nhiên là @mickmackusa Nhưng Hans đang đưa ra một số loại cảm hứng, câu trả lời không đưa ra giải pháp theo nghĩa đen. Nó cần được trau chuốt nhiều hơn, như Josef đã làm trong câu trả lời của mình. Tuy nhiên, bạn đúng ở điểm rằng câu trả lời này không hoàn toàn giải quyết được vấn đề.
Iván Rodríguez Torres

1

Tôi muốn làm như dưới đây, $productsmảng thực tế được đưa ra trong bài toán ngay từ đầu ở đâu.

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

0

Thử cái này

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

Các câu trả lời chỉ có mã có giá trị thấp trên StackOverflow. Vui lòng cập nhật bài đăng của bạn để giải thích cách hoạt động của phương pháp đệ quy, các tình huống thích hợp và các tình huống mà đệ quy là chi phí không cần thiết. Luôn đăng câu trả lời với mục đích giáo dục OP và những khán giả SO lớn hơn. Ps Tôi nghĩ rằng hầu hết các nhà phát triển php sẽ thích &&||thay vì ANDORtrong điều kiện của bạn. Không có lý do gì để tuyên bố current_key. Sự so sánh trên $needlecần phải nghiêm ngặt.
mickmackusa
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.