【问题标题】:PHP multidimensional array search by valuePHP多维数组按值搜索
【发布时间】:2011-10-03 10:36:51
【问题描述】:

我有一个数组,我想在其中搜索 uid 并获取数组的键。

示例

假设我们有以下二维数组:

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

函数调用search_by_uid(100)(第一个用户的uid)应该返回0

函数调用search_by_uid(40489) 应该返回2

我尝试制作循环,但我想要更快的执行代码。

【问题讨论】:

  • 有趣的是,下划线(和 lowdash)库将此函数添加到 javascript...
  • 我写了一个脚本来测试几个答案的性能。它生成一个包含 500k 个成员的数组数组,并在其中搜索最后一个成员中的值。我将接受的答案之类的功能与两个array_column 单线答案进行了比较。我将它们全部修改为返回实际发现的数组,而不仅仅是键,因为通常这是我的用例。函数方法在每种方法的 1000 次运行中得分 0​​.361、search-col 0.184 和 keys-col 0.189 平均微延迟。

标签: php arrays multidimensional-array


【解决方案1】:
function searchForId($id, $array) {
   foreach ($array as $key => $val) {
       if ($val['uid'] === $id) {
           return $key;
       }
   }
   return null;
}

这会奏效。你应该这样称呼它:

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

重要的是要知道,如果您使用=== 运算符比较类型必须完全相同,在此示例中您必须搜索string 或只使用== 而不是===

基于 angoru 的回答。在更高版本的 PHP (>= 5.5.0) 中,您可以使用 one-liner。

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

这是文档:http://php.net/manual/en/function.array-column.php

【讨论】:

  • 您也应该能够在没有 PHP 5.5 的情况下使用 array_map 代替 array_column 来实现这一点。只需将array_column($userdb, 'uid') 替换为array_map(function($v){return $v['uid'];},$userdb)
  • 是的,你是对的。 Lambda 函数从 PHP 5.3 开始可用。更好的是array_search,不是吗?
  • @angoru 我认为原始解决方案(foreach 循环)会执行得更快,因为它会在找到匹配项后立即停止。较新的解决方案必须遍历整个数组一次以提取array_column,然后再循环一次以执行搜索(直到找到匹配项)。较新的解决方案更易于阅读、更简洁,但 OP 专门提出了性能问题
  • @JakubTruneček 。我与问题中给出的相同数组有关。我想通过传递 id 从数组中获取用户名。函数 findUserName(40489) 应该返回“Michael”。怎么可能?
  • @JakubTruneček 嗨,我在我的代码中遇到了这个问题,但我有完全不同的事情。在我的情况下,'uid' 值多次出现,所以我需要获取一组已建立的密钥。
【解决方案2】:

如果您使用的是 (PHP 5 >= 5.5.0),则不必编写自己的函数来执行此操作,只需编写此行即可。

如果你只想要一个结果:

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

多个结果

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

如果你有一个在 cmets 中指向的关联数组,你可以使用:

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

如果你使用 PHP this backport,谢谢 ramsey!

更新:我一直在做一些简单的基准测试,多结果表似乎是最快的,甚至比 Jakub 自定义函数还要快!

【讨论】:

  • 如果我正在搜索的值(在本例中为 40489)出现不止一次并且我想获取它出现的所有键怎么办?
  • 如果值 40489 在数组中出现的次数超过一次,函数将返回一个键数组 ... ?? @angoru
  • 当 $userdb 中的键不以 0,1,2 等开头时,这对我不起作用。说键是 1234,4566 等。array_search 之后的结果键是总是 0,1,2 等等
  • 这不适用于关联数组,但是您可以像这样解决这个问题:array_search(40489, array_combine(array_keys($userdb), array_column($userdb, 'uid')))
  • 注意:如果没有找到大小写,第一个语句返回false,接下来的两个语句返回一个空数组[]
【解决方案3】:

在更高版本的 PHP (>= 5.5.0) 中,您可以使用这个单行:

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

【讨论】:

  • 只需将 array_column 结果放入一个特定的变量中,避免为数组上的每个结果调用 array_column。
【解决方案4】:

以 Jakub 的 excellent answer 为基础,这里有一个更通用的搜索,允许指定密钥(不仅仅是用于 uid):

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

用法:$results = searcharray('searchvalue', searchkey, $array);

【讨论】:

  • 这很有帮助,我觉得我即将使用此解决方案解决我的问题,但我仍然遇到一些问题。您能否提供见解?问题可以在这里找到:stackoverflow.com/questions/28704644/…
【解决方案5】:

看起来array_filter 将是适合此问题的解决方案...

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

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 optional.. Available Values:- ARRAY_FILTER_USE_BOTH OR ARRAY_FILTER_USE_KEY  

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

【讨论】:

  • @BEJAM SHIVA PRASAD 你能帮我解决这个stackoverflow.com/questions/44721195/… 吗?
  • 显示错误:syntax error, unexpected '=&gt;' (T_DOUBLE_ARROW), expecting ';'
  • 您能否粘贴更多信息,我的意思是哪一行以及您的代码和数组结构。
  • @Shihas 我更新了答案,我相信它会得到解决。
【解决方案6】:

我知道这已经被回答了,但我使用了它并在我的代码中对其进行了更多扩展,这样您就不必只通过 uid 进行搜索。我只是想将它分享给任何可能需要该功能的人。

这是我的示例,请记住这是我的第一个答案。我取出了 param 数组,因为我只需要搜索一个特定的数组,但您可以轻松地将它添加进去。我想基本上搜索的不仅仅是 uid。

另外,在我的情况下,由于搜索可能不是唯一的其他字段,可能会返回多个键。

 /**
     * @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;
    }

后来,我最终写了这个来让我搜索另一个值和关联键。所以我的第一个示例允许您在任何特定关联键中搜索一个值,并返回所有匹配项。

第二个示例向您展示了在某个关联键 (first_name) 中找到值 ('Taylor') 的位置 AND 在另一个关联键(使用)中找到另一个值 (true),并且返回所有匹配项(使用名字为“Taylor”且受雇的人的键)。

/**
 * @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;
}

功能使用

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

结果

Array ( [0] => 2 ) 

【讨论】:

    【解决方案7】:

    您可以为此使用 array_column。

    $search_value = '5465';
    $search_key   = 'uid';
    $user = array_search($search_value, array_column($userdb, $search_key));
    
    print_r($userdb[$user]);
    

    5465 是您要搜索的用户 ID,uid 是包含用户 ID 的键,$userdb 是要搜索的数组在问题中定义。

    【讨论】:

      【解决方案8】:

      我修改了以下描述函数array_search 的示例之一。函数searchItemsByKey 通过 $key 从多维数组(N 级)返回所有值。也许,它对某人有用。示例:

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

      功能代码:

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

      【讨论】:

        【解决方案9】:

        这是一个相同的班轮,

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

        【讨论】:

          【解决方案10】:

          我想检查以下数组$arr中的 tha 在子数组中是否存在'abc'

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

          那我可以用这个了

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

          我认为这是最简单的定义方式

          【讨论】:

            【解决方案11】:

            尽管这是一个老问题并且有一个公认的答案,但我认为我会建议对已接受的答案进行一些更改。所以首先,我同意这里接受的答案是正确的。

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

            将预设的“uid”替换为函数中的参数,因此现在调用以下代码意味着您可以在多个数组类型中使用一个函数。微小的变化,但会产生细微的差别。

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

            PHP Fiddle Example

            【讨论】:

            • 我使用 SOF 的另一个原因......更容易用谷歌搜索并找到我自己的代码或我记得的东西......为我自己的公共存储库 +1
            • 顺便说一句,您将结果设置为null,然后在代码中将其与false 进行比较。
            • 更正为返回 false,但如果检查布尔值,null 可能更好
            【解决方案12】:

            我必须使用 un 函数来查找数组中的每个元素。所以我修改了 Jakub Truneček 完成的功能如下:

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

            【讨论】:

              【解决方案13】:
              /**
               * 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;
              }
              

              【讨论】:

                【解决方案14】:

                你可以使用这个功能; https://github.com/serhatozles/ArrayAdvancedSearch

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

                【讨论】:

                  【解决方案15】:
                  $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);
                  

                  【讨论】:

                    【解决方案16】:

                    试试这个

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

                    【讨论】:

                      【解决方案17】:

                      只是分享,也​​许可以这样。

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

                      【讨论】:

                        【解决方案18】:
                        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
                        

                        在上述代码的帮助下,可以从二维数组的任何列中找到任何(部分匹配的)数据,因此可以根据需要找到用户 ID。

                        【讨论】:

                        • 请添加一个短语来解释为什么这可以回答问题
                        • 借助上述代码,可以从二维数组的任何列中找到任何(部分匹配的)数据,因此可以根据需要找到用户 ID
                        【解决方案19】:

                        扩展@mayhem 创建的函数,如果您只想匹配搜索字符串的一部分(大多数),此示例将更像是一个“模糊”搜索:

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

                        例如数组中的值是Welcome to New York!而你想要的只是“纽约!”的第一个实例

                        【讨论】:

                          【解决方案20】:

                          如果问题即

                          $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",
                               ],
                             ];
                          

                          答案:

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

                          【讨论】:

                            【解决方案21】:

                            还没有其他人使用过array_reduce,所以我想我会添加这种方法......

                            $find_by_uid = '100';
                            $is_in_array = array_reduce($userdb, function($carry, $user) use ($find_by_uid){
                                return $carry ? $carry : $user['uid'] === $find_by_uid;
                            }); 
                            // Returns true
                            

                            比 array_search() 更精细地控制“搜索”逻辑。

                            请注意,我在这里使用了严格相等,但您可以选择不同的比较逻辑。 $carry 表示比较需要一次为真,最终结果为真。

                            【讨论】:

                              【解决方案22】:

                              这是一个更好的解决方案,以防您从数据库或多维数组中提取数据

                              多维数组示例:

                              $records = array(
                                          array(
                                              'id' => 2135,
                                              'first_name' => 'John',
                                              'last_name' => 'Doe',
                                          ),
                                          array(
                                              'id' => 3245,
                                              'first_name' => 'Sally',
                                              'last_name' => 'Smith',
                                          ),
                                          array(
                                              'id' => 5342,
                                              'first_name' => 'Jane',
                                              'last_name' => 'Jones',
                                          ),
                                          array(
                                              'id' => 5623,
                                              'first_name' => 'Peter',
                                              'last_name' => 'Doe',
                                          )
                                          );
                              
                              
                                          function search_user_by_name($name, $array) {
                                                           foreach ($array as $keys) {
                                                               foreach ($keys as $key => $_user_record) {
                                                                   if ($_user_record == $name) {
                                                                       return [$key => $_user_record];//Return and array of user
                                                                   }
                                                               }
                                                           }
                                                           return null;
                                                      }
                              

                              调用函数:

                              $results = search_user_by_name('John', $records);
                                       print_r($results);
                                       
                              

                              输出:Array ( [first_name] =&gt; John )

                              【讨论】:

                                【解决方案23】:

                                我一直在寻找类似于 MySQL LIKE %term% 的功能。基于此页面上的答案。我可以从文件中搜索 JSON 数组。

                                user_list.json 如下所示:

                                {
                                  "user-23456": {
                                        "name": "John Doe",
                                        "age": "20",
                                        "email": "doe@sample.com",
                                        "user_id": "23456"
                                    },
                                    "user-09876": {
                                        "name": "Ronojoy Adams",
                                        "age": "35",
                                        "email": "joy@sample.com",
                                        "user_id": "09876"
                                    },
                                    "user-34890": {
                                        "name": "Will Artkin",
                                        "age": "16",
                                        "email": "will@sample.com",
                                        "user_id": "34890"
                                    },
                                }
                                
                                /*
                                *search_key_like
                                */
                                
                                function search_key_like($value, $key, $array) {
                                     $results=array();
                                    $keyword = preg_quote($value, '~');
                                   foreach ($array as $k => $val) {
                                //if name a is spell John and keyword is sent as joh or JOH it will return null
                                //to fix the issue convert the string into lowercase and uppercase
                                       $data=array($val[$key],strtolower($val[$key]),strtoupper($val[$key]));
                                       if (preg_grep('~' . $keyword . '~', $data)) {
                                       array_push($results,$val[$key]);           
                                    }
                                   }
                                   return $results;
                                }
                                

                                用法===拉取JSON文件===

                                 $user_list_json='./user_list.json';
                                    if(file_exists($user_list_json) && file_get_contents($user_list_json)){
                                    $file_json_data=file_get_contents($user_list_json);
                                        
                                    $json_array_data=json_decode($file_json_data,true);
                                        
                                        $user_name_like = search_key_like('ron', 'name', $json_array_data);
                                   
                                         print "<pre>".print_r($user_name_like,true);
                                    }
                                

                                【讨论】:

                                  猜你喜欢
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 2021-11-27
                                  • 2011-05-20
                                  • 2017-07-23
                                  • 2011-12-27
                                  • 2014-06-27
                                  相关资源
                                  最近更新 更多