【问题标题】:Find highest value in multidimensional array [duplicate]在多维数组中查找最大值[重复]
【发布时间】:2013-06-24 17:37:35
【问题描述】:

问题

我有一个类似于下面的多维数组。我想要实现的是一种从数组中查找和检索具有最高“Total”值的方法,现在我知道有一个名为max 的函数,但这不适用于像这样的多维数组。

我想做的是创建一个 foreach 循环并构建一个仅包含总数的新数组,然后使用 max 找到最大值,这将起作用,唯一的问题是检索其余的与该最大值相关的数据。我也不确定这是否是最有效的方法。

有什么想法吗?

Array
(
    [0] => Array
        (
            [Key1] => Key1
            [Total] => 13
        )

    [1] => Array
        (
            [Key2] => Key2
            [Total] => 117
        )

    [2] => Array
        (
            [Key3] => Key3
            [Total] => 39
        )
)

【问题讨论】:

  • 如果您不需要这样的性能 - 两个循环会很好。如果您希望在包含大量元素的数组中获得巨大的性能提升,您应该使用区间树(段树)来存储值。但这是一个庞大的理论,您的情况可能不需要。

标签: php multidimensional-array max


【解决方案1】:

从 PHP 5.5 开始,您可以使用 array_column 获取特定键的值数组,并将其最大化。

max(array_column($array, 'Total'))

【讨论】:

  • 它也适用于 php 7 版本的东西
【解决方案2】:

只需执行simple loop 并比较值或使用array_reduce

$data = array_reduce($data, function ($a, $b) {
    return @$a['Total'] > $b['Total'] ? $a : $b ;
});

print_r($data);

See Live Demo

【讨论】:

  • 虽然使用@ 而不是检查值是否真的存在是不好的做法,但这是迄今为止最正确的答案。 array_reduce 适用于这类解决方案。
  • 如果两个值相同,则返回最后一个值,如何获取第一个值索引?
【解决方案3】:

这是非常基本的算法。

$max = -9999999; //will hold max val
$found_item = null; //will hold item with max val;

foreach($arr as $k=>$v)
{
    if($v['Total']>$max)
    {
       $max = $v['Total'];
       $found_item = $v;
    }
}

echo "max value is $max";
print_r($found_item);

Working demo

【讨论】:

  • 为什么要用-9999999初始化$max
  • 你可以用 "$max= ~PHP_INT_MAX;" 来初始化它检查查找最小值的基础知识。另一种选择是使用数组的第一个成员来初始化它
  • 不,我的问题是为什么?
  • 因为你需要有最小值才能与第一次比较,并且你需要确保这个值小于第一个元素。也可以通过分配数组的第一个元素来完成,但是我需要从数组中的第二个元素开始循环。
  • 您总是可以将其初始化为$max = null;,然后只需再添加一个条件来检查$max 是否已设置,例如if($v['Total']>$max || !$max)。在这种情况下,它第一次运行循环并且没有定义$max 值时,它将设置一个。假设是,即使它是唯一的值,它在技术上也是最大值,无论您硬编码的任意最小值如何。
【解决方案4】:

我知道这个问题很老,但我提供以下答案来回答另一个在被标记为重复后指向此处的问题。这是我在当前答案中没有提到的另一种选择。

我知道有一个名为 max 的函数,但它不适用于像这样的多维数组。

您可以使用array_column 解决这个问题,这使得获得最大值变得非常容易:

$arr = [['message_id' => 1,
             'points' => 3],
        ['message_id' => 2,
             'points' => 2],
        ['message_id' => 3,
             'points' => 2]];

// max value
$max = max(array_column($arr, 'points'));

考虑到您实际上可能需要多个键(如果$max 匹配多个值),获取关联键有点棘手。您可以使用array_map 中的匿名函数执行此操作,并使用array_filter 删除null 值:

// keys of max value
$keys = array_filter(array_map(function ($arr) use ($max) {
    return $arr['points'] == $max ? $arr['message_id'] : null;
}, $arr));

输出:

array(1) {
  [0]=>
  int(1)
}

如果您确实得到了多个键,但只对找到的第一个匹配项感兴趣,那么只需引用 $keys[0]

【讨论】:

    【解决方案5】:

    另一个简单的方法是

    $max  = array_map( function( $arr ) {
      global $last;
      return (int)( ( $arr["Total"] > $last ) ? $arr["Total"] : $last );
    }, $array );
    
    print_r( max( $max ) );
    

    【讨论】:

      【解决方案6】:
      <?php
      $myarray = array(
          0 => array(
              'Key1' => 'Key1',
              'Total' => 13,
          ),
          1 => array(
              'Key2' => 'Key2',
              'Total' => 117,
          ),
          2 => array(
              'Key2' => 'Key3',
              'Total' => 39,
          ),
      );
      
      $out = array();
      foreach ($myarray as $item) {
          $out[] = $item['Total'];
      }
      
      echo max($out); //117
      
      unset($out, $item);
      

      【讨论】:

        【解决方案7】:

        可以使用array_walk(如果需要,array_walk_recursive)来完成

        $arr 是你要搜索的数组

        $largestElement = null;
        
        array_walk($arr, function(&$item, $key) use (&$largestElement) {
            if (!is_array($largestElement) || $largestElement["Total"] < $item["Total"]) {
                $largestElement = $item;
            }
        });
        

        【讨论】:

          【解决方案8】:

          你可以使用 php 的 usort 函数: http://php.net/manual/en/function.usort.php

          这里给出了一个非常说明性的例子:

          <?php
          function cmp($a, $b)
          {
           return strcmp($a["fruit"], $b["fruit"]);
          }
          
          $fruits[0]["fruit"] = "lemons";
          $fruits[1]["fruit"] = "apples";
          $fruits[2]["fruit"] = "grapes";
          
          usort($fruits, "cmp");
          
          while (list($key, $value) = each($fruits)) {
           echo "\$fruits[$key]: " . $value["fruit"] . "\n";
          }
          ?>
          

          所以它会将最大值排序到最后一个数组索引。

          输出:

          $fruits[0]: apples
          $fruits[1]: grapes
          $fruits[2]: lemons
          

          此示例在上述链接中给出

          【讨论】:

          • 我不建议使用复杂的排序算法来处理像从数组中获取单个值这样的事情。实际上,排序应该只在真正需要的时候进行。额外的开销不值得“看起来很酷”的解决方案。
          • @MarcelloMönkemeyer 您在这里指的额外开销到底是什么?要获得单个值(最大值或最小值),需要遍历整个数组(通过比较)。上面的函数也做同样的事情,除非我在这里遗漏了什么!
          • 实际排序,因为它需要多次遍历和比较,以及反复移动和重新定位数组键。根据实现的排序算法(不幸的是,我不知道 PHP 使用哪一个),这可能会呈指数增长。对于小型数组和使用几次时,它可能没有任何明显的区别,但想象一下它经常在像 Symfony 或 Laravel 这样的框架中使用 - 那将是一个巨大的无赖。
          【解决方案9】:

          array_reduce 接受第三个“初始”参数。使用它来避免使用“@”错误抑制的不良做法:

          $data = array_reduce($data, function ($a, $b) {
              return $a['Total'] > $b['Total'] ? $a : $b ;
          },['Total' => 0]);
          
          print_r($data);
          

          PHP 7.4

          $data = array_reduce($data, fn(a,b) => $a['Total'] > $b['Total'] ? $a : $b, ['Total' => 0]);
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-10-14
            • 2016-01-31
            • 2017-04-03
            相关资源
            最近更新 更多