【问题标题】:PHP Search an Array for multiple key / value pairsPHP 在数组中搜索多个键/值对
【发布时间】:2012-12-05 02:26:20
【问题描述】:

我有一个数组列表(对于这个例子,我使用的是手机)。我希望能够搜索多个键/值对并返回它的父数组索引。

例如,这是我的数组:

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

我希望能够执行以下操作:

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

关于我可以或应该如何做到这一点的任何想法或建议?

【问题讨论】:

    标签: php arrays multidimensional-array


    【解决方案1】:

    你可以使用 array_intersect_key 和 array_intersect 和 array_search

    检查array_intersect_key php manual 以获取具有匹配键的项目数组

    和array_intesect php manual 如果项目具有匹配值,则获取数组

    你可以使用$array[key]获取数组中键的值

    并使用 array_search $key = array_search('green', $array); 获取数组中的键值

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

    【讨论】:

    • 我最终使用 foreach 循环遍历 $list_of_phones,然后在数组中搜索每个结果中的值。它有效,但看起来仍然被黑了。如果你能更深入地解释你的方法,我会试一试。
    【解决方案2】:

    我最终做了以下事情。它不漂亮,但效果很好。对于任何阅读的人,请随时使用 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];
                }
            }
        }
    }
    

    像魅力一样工作。

    【讨论】:

    • 令我惊讶的是,这种方法实际上比接受的答案快 5 倍。当然这是一个小数组,但差异很大。这是一个小提琴。 tehplayground.com/#du9XzNFqs
    • 我只是用这种方法比较了 2 个多维数组中的元素,以定义一个数组中的项目是否具有“已​​接收”状态。它就像一个魅力。
    【解决方案3】:

    也许这会有用:

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

    如输出所示,此函数将返回一个包含所有键的数组,其中包含满足所有搜索条件的元素。

    【讨论】:

    • 不错的功能,它按描述工作。第二个foreach 基本上做了array_search 在我上面的操纵代码中所做的事情。由于您是迄今为止唯一真正的答案,并且确实有效,因此我会将您的答案标记为已接受的答案。感谢您的反馈!
    • array_search 并不完全相同。它不检查键,只检查值,所以它不检查Manufacturer 是否是Apple,只有当Apple 在某个数组中时(它们可能在某个时候成为载体) .
    • 这个解决方案应该被接受。只有一个问题:如果某些数组包含NULL(例如:['Manufacturer' => 'Motorola', 'Model' => NULL]),则条件if (!isset($value[$k]) || $value[$k] != $v) 不会触发。所以,我建议改变这个条件:if ((!isset($value[$k]) && $value[$k] !== null) || $value[$k] != $v).
    • 我以前从未听说过continue 有一个可选的数字参数。不错!
    【解决方案4】:

    这种方式适用于像你这样的多维数组:

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

    【讨论】:

      【解决方案5】:

      我通过添加对不同比较运算符的支持来扩展 @MichaelRushton 的代码:

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

      【讨论】:

        【解决方案6】:

        这与@Boolean_Type 相同,但进行了一些改进以简化事情。

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

        这样,你可以像这样简单地搜索:

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

        如果找到,您将拥有如下索引数组:array(1, 25, 33)(这只是一个示例)。

        【讨论】:

          【解决方案7】:
          // $needle example: ["Manufacturer" => "Motorola", "Carrier" => "Verizon"]
          $needle = ['1st-key' => $value1, '2nd-key' => $value2];
          $result = array_filter($haystack, function($item) use ($needle) {
            return ($item['1stkey'] == $needle['1st-key'] & $item['2nd-key'] == $needle['2nd-key']);
          });
          

          我正在使用类似的东西,它可以工作。它返回一个由相应 $haystack 项的右键键入的数组。我认为这更有意义和紧凑。

          【讨论】:

            猜你喜欢
            • 2019-10-29
            • 2019-10-16
            • 2020-01-15
            • 1970-01-01
            • 1970-01-01
            • 2017-01-13
            • 2016-12-12
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多