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.

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

4

7 回答 7

26

也许这会很有用:

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

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

于 2012-12-18T23:24:01.583 回答
5

你可以使用 array_intersect_key 和 array_intersect 和 array_search

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

array_intesect php 手册来获取数组,如果项目具有匹配的值

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

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

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

于 2012-12-17T23:07:54.757 回答
5

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

奇迹般有效。

于 2012-12-18T22:50:08.373 回答
2

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

$test = array_intersect_key($list_of_phones, array(array("Manufacturer" => "Motorola", "Carrier" => "Verizon")));
于 2016-03-05T14:08:14.663 回答
1

我通过添加对不同比较运算符的支持来扩展 @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) }
于 2017-12-18T10:39:20.183 回答
1

这与@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)这只是一个示例)。

于 2017-12-21T00:53:23.980 回答
1
// $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 项的右键键入的数组。我认为这更有意义和紧凑。

于 2021-04-22T15:18:52.853 回答