PHP tìm kiếm mảng đa chiều theo giá trị


331

Tôi có một mảng nơi tôi muốn tìm kiếm uidvà lấy khóa của mảng.

Ví dụ

Giả sử chúng ta có mảng 2 chiều sau:

$userdb = array(
    array(
        'uid' => '100',
        'name' => 'Sandra Shush',
        'pic_square' => 'urlof100'
    ),
    array(
        'uid' => '5465',
        'name' => 'Stefanie Mcmohn',
        'pic_square' => 'urlof100'
    ),
    array(
        'uid' => '40489',
        'name' => 'Michael',
        'pic_square' => 'urlof40489'
    )
);

Cuộc gọi chức năng search_by_uid(100)(uid của người dùng đầu tiên) sẽ trả về 0.

Các cuộc gọi chức năng search_by_uid(40489)sẽ trở lại 2.

Tôi đã thử tạo các vòng lặp, nhưng tôi muốn một mã thực thi nhanh hơn.


thú vị là các thư viện gạch dưới (và lowdash) thêm chức năng này vào javascript ...
ErichBSchulz

9
Tôi đã viết một kịch bản để kiểm tra hiệu suất của một vài câu trả lời. Nó tạo ra một mảng 500k thành viên của các mảng và tìm kiếm thông qua nó để tìm giá trị trong thành viên cuối cùng. Tôi đã so sánh một chức năng như câu trả lời được chấp nhận, với hai array_columncâu trả lời một lót. Tôi đã sửa đổi tất cả để trả về mảng được phát hiện thực tế, không chỉ là khóa, bởi vì đó thường là trường hợp sử dụng của tôi. Phương thức hàm ghi được 0,361, search-col 0.184 và key-col 0.189 độ trễ vi trung bình trên 1000 lần chạy cho mỗi phương thức.
Josh

Câu trả lời:


474
function searchForId($id, $array) {
   foreach ($array as $key => $val) {
       if ($val['uid'] === $id) {
           return $key;
       }
   }
   return null;
}

Điều này sẽ làm việc. Bạn nên gọi nó như thế này:

$id = searchForId('100', $userdb);

Điều quan trọng cần biết là nếu bạn đang sử dụng ===các loại toán tử so sánh phải giống hệt nhau, trong ví dụ này bạn phải tìm kiếm stringhoặc chỉ sử dụng ==thay thế=== .

Dựa trên câu trả lời angoru . Trong các phiên bản sau của PHP ( >= 5.5.0), bạn có thể sử dụng một lớp lót.

$key = array_search('100', array_column($userdb, 'uid'));

Đây là tài liệu: http://php.net/manual/en/feft.array-column.php .


8
Bạn cũng có thể thực hiện điều này mà không cần PHP 5.5 trong một lớp lót bằng cách sử dụng mảng_map thay cho mảng_column. Chỉ cần thay thế array_column($userdb, 'uid')bằngarray_map(function($v){return $v['uid'];},$userdb)
Jesse Green

1
Vâng, bạn đã đúng. Các hàm Lambda có sẵn kể từ PHP 5.3. và tốt hơn là array_search, phải không?
Jakub Truneček

@angoru Tôi nghĩ rằng giải pháp ban đầu ( foreachvòng lặp) sẽ hoạt động nhanh hơn vì nó dừng lại ngay khi tìm thấy kết quả khớp. Giải pháp mới hơn phải lặp lại toàn bộ mảng một lần để trích xuất array_column, sau đó lặp lại lần thứ hai để thực hiện tìm kiếm (cho đến khi tìm thấy kết quả khớp). Giải pháp mới hơn dễ đọc hơn, súc tích hơn, nhưng OP đặc biệt mang đến hiệu suất như một vấn đề
BeetleJuice 27/07/17

@ JakubTruneček. Tôi có một cái gì đó để làm với cùng một mảng được đưa ra trong câu hỏi. Tôi muốn tên người dùng từ mảng bằng cách chuyển id. Hàm findUserName (40361) sẽ trả về 'Michael'. Làm thế nào nó có thể?
Ashok Gujjar

@ JakubTruneček Xin chào, tôi đã gặp phải vấn đề này trong mã của mình nhưng tôi có một điều hoàn toàn khác. Trong trường hợp của tôi, giá trị 'uid' xuất hiện nhiều lần vì vậy tôi cần nhận được một mảng các khóa thành lập.
Bhavin Thummar

314

Nếu bạn đang sử dụng (PHP 5> = 5.5.0), bạn không phải viết hàm riêng của mình để thực hiện việc này, chỉ cần viết dòng này và thế là xong.

Nếu bạn chỉ muốn một kết quả:

$key = array_search(40489, array_column($userdb, 'uid'));

Cho nhiều kết quả

$keys = array_keys(array_column($userdb, 'uid'), 40489);

Trong trường hợp bạn có một mảng kết hợp như được chỉ ra trong các ý kiến ​​bạn có thể thực hiện với:

$keys = array_keys(array_combine(array_keys($userdb), array_column($userdb, 'uid')),40489);

Nếu bạn đang sử dụng PHP <5.5.0, bạn có thể sử dụng backport này , cảm ơn ramsey!

Cập nhật: Tôi đã thực hiện một số điểm chuẩn đơn giản và biểu mẫu nhiều kết quả dường như là nhanh nhất, thậm chí nhanh hơn chức năng tùy chỉnh Jakub!


Điều gì xảy ra nếu giá trị tôi đang tìm kiếm (trong ví dụ này là 40,49) xuất hiện nhiều hơn một lần và tôi muốn nhận tất cả các khóa mà nó xuất hiện?
Dimitris Papageorgiou

nếu giá trị 40361 xuất hiện nhiều hơn thì một lần trong mảng, hàm sẽ trả về một mảng các khóa ... ?? @angoru
jishan

Nếu bạn sử dụng trường hợp thứ hai cho nhiều kết quả, bạn sẽ nhận được một loạt các khóa.
angoru

2
Điều này không hoạt động với tôi khi khóa trong $ userdb không bắt đầu bằng 0,1, 2, v.v. và nói rằng khóa là 1234,4566, v.v. Các khóa kết quả sau mảng_search luôn là 0,1,2 và vì vậy vào
Kaushtuv

1
Điều này sẽ không hoạt động với một mảng kết hợp, tuy nhiên bạn có thể giải quyết như vậy: array_search(40489, array_combine(array_keys($userdb), array_column($userdb, 'uid')))
John Mellor

32

Trong các phiên bản sau của PHP (> = 5.5.0), bạn có thể sử dụng một lớp lót này:

$key = array_search('100', array_column($userdb, 'uid'));

Chỉ cần đặt kết quả mảng_column trong một biến cụ thể để tránh mảng_column được gọi cho mỗi kết quả trên mảng.
Maykonn

26

Xây dựng câu trả lời xuất sắc của Jakub , đây là một tìm kiếm tổng quát hơn sẽ cho phép khóa được chỉ định (không chỉ cho uid):

function searcharray($value, $key, $array) {
   foreach ($array as $k => $val) {
       if ($val[$key] == $value) {
           return $k;
       }
   }
   return null;
}

Sử dụng: $results = searcharray('searchvalue', searchkey, $array);


Điều này rất hữu ích, tôi cảm thấy như mình đang cố gắng giải quyết vấn đề của mình bằng giải pháp này nhưng tôi vẫn gặp một số vấn đề. Có lẽ bạn có thể cung cấp cái nhìn sâu sắc? Câu hỏi có thể được tìm thấy ở đây: stackoverflow.com/questions/28704644/ từ
jasenmp

19

Tôi biết điều này đã được trả lời, nhưng tôi đã sử dụng nó và mở rộng thêm một chút trong mã của tôi để bạn không phải tìm kiếm chỉ bằng uid. Tôi chỉ muốn chia sẻ nó cho bất cứ ai khác có thể cần chức năng đó.

Đây là ví dụ của tôi và xin hãy nhớ rằng đây là câu trả lời đầu tiên của tôi. Tôi lấy ra mảng param vì tôi chỉ cần tìm kiếm một mảng cụ thể, nhưng bạn có thể dễ dàng thêm nó vào. Tôi muốn tìm kiếm về cơ bản không chỉ là uid.

Ngoài ra, trong tình huống của tôi, có thể có nhiều khóa để trả về do kết quả tìm kiếm của các trường khác có thể không phải là duy nhất.

 /**
     * @param array multidimensional 
     * @param string value to search for, ie a specific field name like name_first
     * @param string associative key to find it in, ie field_name
     * 
     * @return array keys.
     */
     function search_revisions($dataArray, $search_value, $key_to_search) {
        // This function will search the revisions for a certain value
        // related to the associative key you are looking for.
        $keys = array();
        foreach ($dataArray as $key => $cur_value) {
            if ($cur_value[$key_to_search] == $search_value) {
                $keys[] = $key;
            }
        }
        return $keys;
    }

Sau đó, tôi đã kết thúc việc viết này để cho phép tôi tìm kiếm một giá trị khác và khóa kết hợp. Vì vậy, ví dụ đầu tiên của tôi cho phép bạn tìm kiếm một giá trị trong bất kỳ khóa kết hợp cụ thể nào và trả về tất cả các kết quả khớp.

Ví dụ thứ hai này cho bạn thấy nơi tìm thấy một giá trị ('Taylor') trong một khóa kết hợp nhất định (First_name) một giá trị khác (true) được tìm thấy trong một khóa kết hợp khác (được sử dụng) và trả về tất cả các kết quả khớp (Khóa nơi mọi người có tên 'Taylor' VÀ được tuyển dụng).

/**
 * @param array multidimensional 
 * @param string $search_value The value to search for, ie a specific 'Taylor'
 * @param string $key_to_search The associative key to find it in, ie first_name
 * @param string $other_matching_key The associative key to find in the matches for employed
 * @param string $other_matching_value The value to find in that matching associative key, ie true
 * 
 * @return array keys, ie all the people with the first name 'Taylor' that are employed.
 */
 function search_revisions($dataArray, $search_value, $key_to_search, $other_matching_value = null, $other_matching_key = null) {
    // This function will search the revisions for a certain value
    // related to the associative key you are looking for.
    $keys = array();
    foreach ($dataArray as $key => $cur_value) {
        if ($cur_value[$key_to_search] == $search_value) {
            if (isset($other_matching_key) && isset($other_matching_value)) {
                if ($cur_value[$other_matching_key] == $other_matching_value) {
                    $keys[] = $key;
                }
            } else {
                // I must keep in mind that some searches may have multiple
                // matches and others would not, so leave it open with no continues.
                $keys[] = $key;
            }
        }
    }
    return $keys;
}

Sử dụng chức năng

$data = array(
    array(
        'cust_group' => 6,
        'price' => 13.21,
        'price_qty' => 5
    ),
    array(
        'cust_group' => 8,
        'price' => 15.25,
        'price_qty' => 4
    ),
    array(
        'cust_group' => 8,
        'price' => 12.75,
        'price_qty' => 10
    )
);

$findKey = search_revisions($data,'8', 'cust_group', '10', 'price_qty');
print_r($findKey);

Kết quả

Array ( [0] => 2 ) 

10

Có vẻ mảng_filter sẽ là giải pháp phù hợp cho việc này ...

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

Mã PHP

<?php 
$search = 5465;
$found = array_filter($userdb,function($v,$k) use ($search){
  return $v['uid'] == $search;
},ARRAY_FILTER_USE_BOTH) // With latest PHP third parameter is mandatory.. Available Values:- ARRAY_FILTER_USE_BOTH OR ARRAY_FILTER_USE_KEY  

$values= print_r(array_value($found)); 
$keys =  print_r(array_keys($found)); 

@BEJAM SHIVA PRASAD bạn có thể vui lòng giúp tôi với stackoverflow.com/questions/44721195/ này không?
Valay

hiển thị một lỗi:syntax error, unexpected '=>' (T_DOUBLE_ARROW), expecting ';'
Shihas

Bạn có thể vui lòng dán thêm thông tin Tôi có nghĩa là dòng nào và mã và cấu trúc mảng của bạn.
PRJAD BEJGAM SHIVA

@Shihas Tôi cập nhật câu trả lời, tôi chắc chắn nó sẽ được giải quyết.
PRJAD BEJGAM SHIVA

9

Tôi đã sửa đổi một trong các ví dụ dưới đây mô tả hàm Array_search . Hàm searchItemsByKeytrả về tất cả (các) giá trị bằng khóa $ từ mảng đa chiều (mức N). Có lẽ, nó sẽ hữu ích cho ai đó. Thí dụ:

 $arr = array(
     'XXX'=>array(
               'YYY'=> array(
                    'AAA'=> array(
                          'keyN' =>'value1'
                   )
               ),
              'ZZZ'=> array(
                    'BBB'=> array(
                          'keyN' => 'value2'
                   )
               )
              //.....
           )
);


$result = searchItemsByKey($arr,'keyN');

print '<pre>';
print_r($result);
print '<pre>';
// OUTPUT
Array
(
  [0] => value1
  [1] => value2
)

Mã chức năng:

function searchItemsByKey($array, $key)
{
   $results = array();

  if (is_array($array))
  {
    if (isset($array[$key]) && key($array)==$key)
        $results[] = $array[$key];

    foreach ($array as $sub_array)
        $results = array_merge($results, searchItemsByKey($sub_array, $key));
  }

 return  $results;
}

7

Đây là một lớp lót cho cùng,

$pic_square = $userdb[array_search($uid,array_column($userdb, 'uid'))]['pic_square'];

3

Mặc dù đây là một câu hỏi cũ và có câu trả lời được chấp nhận, Nghĩ rằng tôi sẽ đề nghị một thay đổi cho câu trả lời được chấp nhận .. Vì vậy, trước hết, tôi đồng ý câu trả lời được chấp nhận là chính xác ở đây.

function searchArrayKeyVal($sKey, $id, $array) {
   foreach ($array as $key => $val) {
       if ($val[$sKey] == $id) {
           return $key;
       }
   }
   return false;
}

Thay thế cài đặt 'uid' bằng một tham số trong hàm thay vào đó, vì vậy bây giờ gọi mã dưới đây có nghĩa là bạn có thể sử dụng một hàm trên nhiều loại mảng. Thay đổi nhỏ, nhưng một trong những làm cho sự khác biệt nhỏ.

    // Array Data Of Users
$userdb = array (
    array ('uid' => '100','name' => 'Sandra Shush','url' => 'urlof100' ),
    array ('uid' => '5465','name' => 'Stefanie Mcmohn','url' => 'urlof100' ),
    array ('uid' => '40489','name' => 'Michael','url' => 'urlof40489' ),
);

// Obtain The Key Of The Array
$arrayKey = searchArrayKeyVal("uid", '100', $userdb);
if ($arrayKey!==false) {
    echo "Search Result: ", $userdb[$arrayKey]['name'];
} else {
    echo "Search Result can not be found";
}

Ví dụ về Fiddle PHP


Một lý do khác khiến tôi sử dụng SOF ... dễ dàng hơn để tìm google và tìm mã của riêng tôi hoặc một cái gì đó tôi nhớ .. +1 cho kho lưu trữ công khai của riêng tôi
Angry 84

BTW, bạn đang đặt kết quả nullvà sau đó trong mã, bạn đang so sánh nó với false.
Taha Paksu

Sửa chữa bằng trả về false thay vào đó, nhưng null có thể tốt hơn trong việc kiểm tra booleans
Angry 84

2

Tôi muốn kiểm tra tha trong mảng sau $arrcó 'abc' tồn tại trong mảng phụ hay không

$arr = array(
    array(
        'title' => 'abc'
    )
);

Sau đó tôi có thể sử dụng

$res = array_search('abc', array_column($arr, 'title'));
if($res == ''){
    echo 'exists';
} else {
    echo 'notExists';
}

Tôi nghĩ rằng đây là cách đơn giản nhất để định nghĩa


1

Tôi đã phải sử dụng hàm un tìm mọi phần tử trong một mảng. Vì vậy, tôi đã sửa đổi chức năng được thực hiện bởi Jakub Truneček như sau:

function search_in_array_r($needle, $array) {
    $found = array();
    foreach ($array as $key => $val) {
        if ($val[1] == $needle) {
            array_push($found, $val[1]);
        }
    }
    if (count($found) != 0)
        return $found;
    else
        return null;
}

1
/**
 * searches a simple as well as multi dimension array
 * @param type $needle
 * @param type $haystack
 * @return boolean
 */
public static function in_array_multi($needle, $haystack){
    $needle = trim($needle);
    if(!is_array($haystack))
        return False;

    foreach($haystack as $key=>$value){
        if(is_array($value)){
            if(self::in_array_multi($needle, $value))
                return True;
            else
               self::in_array_multi($needle, $value);
        }
        else
        if(trim($value) === trim($needle)){//visibility fix//
            error_log("$value === $needle setting visibility to 1 hidden");
            return True;
        }
    }

    return False;
}

1

bạn có thể sử dụng chức năng này; https://github.com/serhatozles/ArrayAdvifiedSearch

<?php 
include('ArraySearch.php');

$query = "a='Example World' and b>='2'";

$Array = array(
'a' => array('d' => '2'),
array('a' => 'Example World','b' => '2'),
array('c' => '3'), array('d' => '4'),
);

$Result = ArraySearch($Array,$query,1);

echo '<pre>';
print_r($Result);
echo '</pre>'; 

// Output:
// Array
// (
//    [0] => Array
//        (
//            [a] => Example World
//            [b] => 2
//        )
//
// )

1
$a = ['x' => ['eee', 'ccc'], 'b' => ['zzz']];

$found = null;
$search = 'eee';

array_walk($a, function ($k, $v) use ($search, &$found) {
    if (in_array($search, $k)) {
        $found = $v;
    }
});

var_dump($found);

1

Thử cái này

<?php
 function recursive_array_search($needle,$haystack) {
    foreach($haystack as $key=>$value) {
        $current_key=$key;
        if($needle===$value OR (is_array($value) && 
            recursive_array_search($needle,$value) !== false)) {
             return $current_key;
        }
    }
    return false;
 }
 ?>

1

Chỉ cần chia sẻ, có thể như thế này.

if( ! function_exists('arraySearchMulti')){
function arraySearchMulti($search,$key,$array,$returnKey=false)
{
    foreach ($array as $k => $val) {
        if (isset($val[$key])) {
            if ((string)$val[$key] == (string)$search) {
                return ($returnKey ? $k : $val);
            }
        }else{
            return (is_array($val) ? arraySearchMulti($search,$key,$val,$returnKey) : null);
        }
    }
    return null;
}}

0

Cũng thử cái này

function search_in_array($srchvalue, $array)
{
    if (is_array($array) && count($array) > 0)
    {
        $foundkey = array_search($srchvalue, $array);
        if ($foundkey === FALSE)
        {
            foreach ($array as $key => $value)
            {
                if (is_array($value) && count($value) > 0)
                {
                    $foundkey = search_in_array($srchvalue, $value);
                    if ($foundkey != FALSE)
                        return $foundkey;
                }
            }
        }
        else
            return $foundkey;
    }
}

0
for( $i =0; $i < sizeof($allUsers); $i++)
    {   
    $NEEDLE1='firstname';
    $NEEDLE2='emailAddress';
    $sterm='Tofind';
     if(isset($allUsers[$i][$NEEDLE1]) && isset($allUsers[$i][$NEEDLE2])
        {
            $Fname= $allUsers[$i][$NEEDLE1];
            $Lname= $allUsers[$i][$NEEDLE2];

            $pos1 = stripos($Fname, $sterm);
            $pos2=stripos($Lname, $sterm);//not case sensitive 

            if($pos1 !== false ||$pos2 !== false)
            {$resultsMatched[] =$allUsers[$i];}
            else
            {   continue;}              
        }

}
Print_r($resultsMatched); //will give array for matched values even partially matched

Với sự trợ giúp của mã trên, người ta có thể tìm thấy bất kỳ dữ liệu (khớp một phần) từ bất kỳ cột nào trong mảng 2D để có thể tìm thấy id người dùng theo yêu cầu trong câu hỏi.


Vui lòng thêm một cụm từ để giải thích lý do tại sao điều này trả lời câu hỏi
Lorenz Meyer

Trợ giúp trắng của mã trên, người ta có thể tìm thấy bất kỳ dữ liệu (khớp một phần) nào từ bất kỳ cột nào trong mảng 2D để có thể tìm thấy id người dùng theo yêu cầu trong câu hỏi
sandeep sharma

0

Mở rộng trên hàm @mayhem đã tạo, ví dụ này sẽ giống với tìm kiếm "mờ" hơn trong trường hợp bạn chỉ muốn khớp một phần ( hầu hết ) của chuỗi tìm kiếm:

 function searchArrayKeyVal($sKey, $id, $array) {
    foreach ($array as $key => $val) {
        if (strpos(strtolower($val[$sKey]), strtolower(trim($id))) !== false) {
            return $key;
        }
    }
         return false;
 }

Ví dụ, giá trị trong mảng là Chào mừng bạn đến New York! và bạn muốn bản đầu tiên của "New York!"


0
$search1 = 'demo';
$search2 = 'bob';
$arr = array('0' => 'hello','1' => 'test','2' => 'john','3' => array('0' => 'martin', '1' => 'bob'),'4' => 'demo');
foreach ($arr as $value) { 
    if (is_array($value)) { 
        if (in_array($search2, $value)) { 
            echo "successsfully";    
            //execute your code 
        }
    } else {  
        if ($value == $search1) { 
            echo "success";
        }
    }
 }

0

Nếu câu hỏi tức là

$a = [
     [
       "_id" => "5a96933414d48831a41901f2",
       "discount_amount" => 3.29,
       "discount_id" => "5a92656a14d488570c2c44a2",
     ],
     [
       "_id" => "5a9790fd14d48879cf16a9e8",
       "discount_amount" => 4.53,
       "discount_id" => "5a9265b914d488548513b122",
     ],
     [
       "_id" => "5a98083614d488191304b6c3",
       "discount_amount" => 15.24,
       "discount_id" => "5a92806a14d48858ff5c2ec3",
     ],
     [
       "_id" => "5a982a4914d48824721eafe3",
       "discount_amount" => 45.74,
       "discount_id" => "5a928ce414d488609e73b443",
     ],
    [
       "_id" => "5a982a4914d48824721eafe55",
       "discount_amount" => 10.26,
       "discount_id" => "5a928ce414d488609e73b443",
     ],
   ];

Trả lời:

function searchForId($id, $array) {
    $did=0;
    $dia=0;
   foreach ($array as $key => $val) {
       if ($val['discount_id'] === $id) {
           $dia +=$val['discount_amount'];
           $did++;
       }
   }
    if($dia != '') {
        echo $dia;
        var_dump($did);
    }
   return null;
};
print_r(searchForId('5a928ce414d488609e73b443',$a));

0

giải pháp của tôi:

function searchArrayForField($array, $field, $value) {
    $i = 0;
    foreach ($array as &$row) {
        if ($row[$field] === $value) {
            return $i;
        }
        $i++
    }
    return '';
}
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.