PHP - tìm mục nhập theo thuộc tính đối tượng từ một mảng các đối tượng


174

Các mảng trông như:

[0] => stdClass Object
        (
            [ID] => 420
            [name] => Mary
         )

[1] => stdClass Object
        (
            [ID] => 10957
            [name] => Blah
         )
...

Và tôi có một biến số nguyên được gọi là $v.

Làm thế nào tôi có thể chọn một mục mảng có một đối tượng trong đó thuộc IDtính có $vgiá trị?

Câu trả lời:


189

Bạn có thể lặp lại mảng, tìm kiếm bản ghi cụ thể (ok trong một lần tìm kiếm duy nhất) hoặc xây dựng một hashmap bằng cách sử dụng một mảng kết hợp khác.

Đối với trước đây, một cái gì đó như thế này

$item = null;
foreach($array as $struct) {
    if ($v == $struct->ID) {
        $item = $struct;
        break;
    }
}

Xem câu hỏi này và các câu trả lời tiếp theo để biết thêm thông tin về câu hỏi sau - Mảng PHP tham khảo theo nhiều chỉ mục


3
thiết lập $ item thành null là không cần thiết.
dAm2K

32
Rất tiếc, đây là :) Đó là trong trường hợp mục tìm kiếm không có trong mảng. Ngoài ra, bạn có thể sử dụng isset($item)nhưng tôi thích khởi tạo các biến một cách chính xác
Phil

3
Đối với những bạn có giá trị chính được đặt thành chuỗi sử dụngif($v == $struct["ID"]){...
wbadart 7/07/2015

67

YurkamTim đã đúng. Nó chỉ cần một sửa đổi:

Sau hàm ($), bạn cần một con trỏ tới biến ngoài bằng cách "use (& $ searchValue)" và sau đó bạn có thể truy cập biến ngoài. Ngoài ra, bạn có thể sửa đổi nó.

$neededObject = array_filter(
    $arrayOfObjects,
    function ($e) use (&$searchedValue) {
        return $e->id == $searchedValue;
    }
);

2
Bạn nói đúng về sửa đổi và đó là một phương pháp gọn gàng, nhưng tôi đã kiểm tra tốc độ so với việc lặp qua đối tượng - chính bạn, bởi vì như @phil đã chỉ ra, mảng_filter cũng đang làm điều này - và phương pháp này mất khoảng năm thời gian lâu hơn Đối tượng thử nghiệm của tôi không phải là một đối tượng lớn, do đó có thể còn tồi tệ hơn.
Nicolai

9
Các &là không cần thiết khi nhập khẩu $searchedValuevào phạm vi đóng cửa. Cái &này được sử dụng để tạo một tham chiếu chỉ cần thiết nếu $searchedValueđã được sửa đổi bên trong bao đóng.
Stefan Gehrig

Thật tuyệt. Tôi không biết PHP có thể làm những việc như thế. Tôi nghĩ rằng việc sử dụng globallà duy nhất để chia sẻ dữ liệu trong các chức năng! Nhưng thật đáng tiếc nếu điều này thực sự chậm. :(
NoOne

13
TS yêu cầu một mục duy nhất, mã này trả về một mảng.
Pavel Vlasov

57
$arr = [
  [
    'ID' => 1
  ]
];

echo array_search(1, array_column($arr, 'ID')); // prints 0 (!== false)

3
Không chắc chắn tại sao đây không phải là câu trả lời ưa thích. Có phải vì bạn đang gọi hai chức năng?
doz87

1
Tôi nghĩ rằng tôi đã quá muộn cho bữa tiệc;) Sự thiếu hụt và dễ đọc của nó mà không có bất kỳ vòng lặp và phá vỡ nào sẽ làm cho nó hợp lý. Nhưng chưa có điểm chuẩn nào. Bạn có rất nhiều tùy chọn trong PHP để đạt được điều tương tự.
Tim

3
Giải pháp rất thanh lịch. Cũng hoạt động với một mảng các đối tượng trong PHP 7. Đối với PHP 5: Array_search ($ object-> id, Array_map (function ($ object) {return $ object-> id;}, $ object)); Đối với PHP 7: Array_search ($ object-> id, Array_column ($ object, 'id'));
Mike

3
Đây không phải là câu trả lời ưa thích vì op yêu cầu mảng đối tượng và câu trả lời này chỉ xử lý các mảng thuần túy.
Dwza

8
Điều đó không đúng. mã này xử lý mảng các đối tượng / mảng không phẳng
Tim

31

Tôi đã tìm thấy giải pháp thanh lịch hơn ở đây . Thích nghi với câu hỏi có thể giống như:

$neededObject = array_filter(
    $arrayOfObjects,
    function ($e) use ($searchedValue) {
        return $e->id == $searchedValue;
    }
);

16
+1 nhưng array_filtertrả về một mảng và sẽ không dừng ở giá trị đầu tiên được tìm thấy.
Carlos Campderrós

4
Nó không được nhận ra $searchedValuebên trong chức năng. Nhưng bên ngoài nó là.
M. Ahmad Zafar

4
Đối với người mới bắt đầu, mã này không hoạt động như $searchedValuenằm ngoài phạm vi đóng. Thứ hai, bạn nghĩ các phương thức mảng này hoạt động như thế nào? Tất cả đều lặp lại nội bộ
Phil

1
Trong thời gian của nhiều lõi, điều này - không may trong các môi trường lập trình khác - có thể được xử lý song song, vòng lặp ở trên không nhất thiết
FloydThreepwood

3
Để sử dụng $searchedValuecần viếtfunction ($e) use ($searchedValue) {
Vilintritenmert

20

Sử dụng mảng_column để lập chỉ mục lại sẽ tiết kiệm thời gian nếu bạn cần tìm nhiều lần:

$lookup = array_column($arr, NULL, 'id');   // re-index by 'id'

Sau đó, bạn có thể chỉ đơn giản là tùy $lookup[$id]ý.


3
Đây là câu trả lời tuyệt vời nhất, ngay cả khi nó không trực quan nhất ...
Thiago Natanael

11
class ArrayUtils
{
    public static function objArraySearch($array, $index, $value)
    {
        foreach($array as $arrayInf) {
            if($arrayInf->{$index} == $value) {
                return $arrayInf;
            }
        }
        return null;
    }
}

Sử dụng nó theo cách bạn muốn sẽ là một cái gì đó như:

ArrayUtils::objArraySearch($array,'ID',$v);

9

Thử

$entry = current(array_filter($array, function($e) use($v){ return $e->ID==$v; }));

ví dụ làm việc ở đây


1
Rất rất hữu ích! Cảm ơn nhé người anh em!
Fernando León

Nó sẽ không dừng lại ở phần tử được tìm thấy đầu tiên, phải không?
yaugenka

7

Sửa một lỗi nhỏ của @YurkaTim , giải pháp của bạn có hiệu quả với tôi nhưng thêm use:

Để sử dụng $searchedValue, bên trong hàm, một giải pháp có thể là use ($searchedValue)sau các tham số hàm function ($e) HERE.

các array_filterchức năng chỉ trở về $neededObjectnếu điều kiện về lợi nhuận làtrue

Nếu $searchedValuelà một chuỗi hoặc số nguyên:

$searchedValue = 123456; // Value to search.
$neededObject = array_filter(
    $arrayOfObjects,
    function ($e) use ($searchedValue) {
        return $e->id == $searchedValue;
    }
);
var_dump($neededObject); // To see the output

Nếu $searchedValuelà mảng mà chúng ta cần kiểm tra với một danh sách:

$searchedValue = array( 1, 5 ); // Value to search.
$neededObject  = array_filter(
    $arrayOfObjects,
    function ( $e ) use ( $searchedValue ) {
        return in_array( $e->term_id, $searchedValue );
    }
);
var_dump($neededObject); // To see the output

1
Tôi nghĩ dòng cuối cùng phải là var_dump($neededObject);:)
Sliq

3

Đôi khi tôi thích sử dụng hàm Array_reduce () để thực hiện tìm kiếm. Nó tương tự như Array_filter () nhưng không ảnh hưởng đến mảng tìm kiếm, cho phép bạn thực hiện nhiều tìm kiếm trên cùng một mảng đối tượng.

$haystack = array($obj1, $obj2, ...); //some array of objects
$needle = 'looking for me?'; //the value of the object's property we want to find

//carry out the search
$search_results_array = array_reduce(
  $haystack,

  function($result_array, $current_item) use ($needle){
      //Found the an object that meets criteria? Add it to the the result array 
      if ($current_item->someProperty == $needle){
          $result_array[] = $current_item;
      }
      return $result_array;
  },
  array() //initially the array is empty (i.e.: item not found)
);

//report whether objects found
if (count($search_results_array) > 0){
  echo "found object(s): ";
  print_r($search_results_array[0]); //sample object found
} else {
  echo "did not find object(s): ";
}

1
Bạn có một lỗi đánh máy bên trong điều kiện của bạn, nơi bạn đang thêm tot he results_array. Nó nên là thế này:if ($current_item->someProperty == $needle){ $result_array[] = $current_item; }
adrum

Điều chỉnh. Cảm ơn @adrum!
yuvilio

1

Tôi đã làm điều này với một số loại sơ đồ bàn phím Java. Nếu bạn làm điều đó, bạn không cần phải lặp lại mảng đối tượng của mình mỗi lần.

<?php

//This is your array with objects
$object1 = (object) array('id'=>123,'name'=>'Henk','age'=>65);
$object2 = (object) array('id'=>273,'name'=>'Koos','age'=>25);
$object3 = (object) array('id'=>685,'name'=>'Bram','age'=>75);
$firstArray = Array($object1,$object2);
var_dump($firstArray);

//create a new array
$secondArray = Array();
//loop over all objects
foreach($firstArray as $value){
    //fill second        key          value
    $secondArray[$value->id] = $value->name;
}

var_dump($secondArray);

echo $secondArray['123'];

đầu ra:

array (size=2)
  0 => 
    object(stdClass)[1]
      public 'id' => int 123
      public 'name' => string 'Henk' (length=4)
      public 'age' => int 65
  1 => 
    object(stdClass)[2]
      public 'id' => int 273
      public 'name' => string 'Koos' (length=4)
      public 'age' => int 25
array (size=2)
  123 => string 'Henk' (length=4)
  273 => string 'Koos' (length=4)
Henk

Ah, reindexing mảng bằng id! Tôi làm điều này thường và nó làm cho mọi thứ đẹp hơn.
Kzqai

1

Cách để ngay lập tức nhận được giá trị đầu tiên:

$neededObject = array_reduce(
    $arrayOfObjects,
    function ($result, $item) use ($searchedValue) {
        return $item->id == $searchedValue ? $item : $result;
    }
);

0

Tôi đã đăng những gì tôi sử dụng để giải quyết vấn đề rất hiệu quả ở đây bằng Thuật toán tìm kiếm nhị phân nhanh: https://stackoverflow.com/a/52786742/1678210

Tôi không muốn sao chép cùng một câu trả lời. Một số người khác đã hỏi nó một chút khác nhau nhưng câu trả lời là như nhau.

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.