php在二维数组中查找max,但返回数组的另一个元素(';id';)

php在二维数组中查找max,但返回数组的另一个元素(';id';),php,multidimensional-array,mapreduce,max,Php,Multidimensional Array,Mapreduce,Max,这是我的数组示例$data[][] Array( [0] => Array ( [id] => 1349 [rating1] => 1.9378838029981E-7 [rating2] => 1.1801796607774 ) [1] => Array ( [id] => 1350 [rating1] =

这是我的数组示例
$data[][]

Array( [0] => Array ( [id] => 1349
                      [rating1] => 1.9378838029981E-7
                      [rating2] => 1.1801796607774     )
       [1] => Array ( [id] => 1350
                      [rating1] => 5.5499981876923E-7
                      [rating2] => 1.5121329727308     )
       [2] => Array ( [id] => 1377
                      [rating1] => 0.00023952225410117
                      [rating2] => 2.1947077830236     )
       [3] => Array ( [id] => 1378
                      [rating1] => 0.00022982302863634
                      [rating2] => 2.2135588326622     )
       [4] => Array ( [id] => 1379
                      [rating1] => 0.00026272979843585
                      [rating2] => 2.2388295595073     )
       [5] => Array ( [id] => 1380
                      [rating1] => 0.0002788640872546
                      [rating2] => 2.1815325502993     )
)
我想查找
max($data[][rating?])
但返回
$data[id][max\u rating?]
即与
max
值关联的
id

找到一个特定的最大值很容易,比如说
rating1
,我使用了array\u reduce,如下所示(其灵感来源于):

现在我有两个问题:
1.我如何扩展以上数组_reduce以包含rating2?我还有其他的评级X。
2.我不想要
max
值,而是想要与
max
关联的
$data[][id]

我不太关心Q1,但第二个问题很重要,因为我不想再次搜索数组以获得关联的
$data[][id]

一种思路是使用array\u map而不是array\u reduce,但我无法想出一个同时传递
[id]
[rating?]
的版本。此外,当我一次尝试
max()
多个
评级?
时,也会出现一些复杂情况,因为每个评级都有不同的
max
,这反过来又与不同的
[id]
关联

编辑:为了清楚起见,我需要与每个
评级的
max
相关联的所有
id
s?

假设您的数组未排序,您必须至少循环一次(手动或使用内置函数)。我将使用以下代码:

$array = array(
  array( 'id' => 1349, 'sudhi_rating1' => 1.9378838029981E-7, 'sudhi_rating2' => 1.1801796607774 ),
  array( /* … */ ),
  /* … */
);

$idx_max = 0;
foreach($array as $idx => $item) {
  if($item['sudhi_rating1'] > $array[$idx_max]['sudhi_rating1'])
    $idx_max = $idx;
}

echo "Rating 1 has max value at id ", htmlspecialchars($array[$idx_max]['id']);
您可以扩展代码,一次检查多个评级(将
$idx_max
作为数组本身并添加更多的ifs):

结果:没有条目
$max=NULL
否则
$max['id']
是具有最大评级的id

或者,此通用代码

$max = array_reduce($data, function($a, $b) {
   if (is_null($a)) return $b;
   return maxRating($a)>maxRating($b) ? $a : $b;
 });

function maxRating($row){
   return (max(array_intersect_key($row,array_flip(array_filter(array_keys($row),function ($item) { return strstr($item,'rating')!==FALSE;})))));
}
将查找所有评级的表格评级

编辑——代码试图回答Q1,这里是Q2的答案

$max = array_reduce($data, function($a, $b) {    
  if (is_null($a)) return $b;
  return $a['rating1']>$b['rating1'] ? $a : $b;
});
EDIT2——这是一个针对任意数量评级的通用解决方案?纵队

$ratingKeys=array_filter(array_keys($data[0]),function ($item) { return strstr($item,'rating')!==FALSE;});

$max = array_reduce($data,function($a,$b) use (&$ratingKeys) {
  if (is_null($a)) {
    $a=array();
    foreach($ratingKeys as $key) {
      $a[$key]=$b[$key];
      $a[$key.'_id'] = $b['id'];
     }
     return $a;
  }
  foreach($ratingKeys as $key) {
    if ($a[$key]<$b[$key]) {
      $a[$key]=$b[$key];
      $a[$key.'_id']=$b['id'];
    }
  }
  return $a;
});
编辑3——如果将输入数组的格式更改为使用id作为数组键,则可以大大简化

$max=array_reduce(array_keys($data),function ($a,$b) use (&$data) {
  if (is_null($a)) $a=array();
    foreach(array_keys($data[$b]) as $item) {
      if (!isset($a[$item]) {
        $a[$item] = $b;
      } else {
        if ($data[$a[$item]][$item]) < $data[$b][$item]) $a[$item]=$b;
      }
    return $a;
  }
});

这看起来像是数据库中的表。如果是这样,请在db级别进行过滤!不,这不是,根据表中的数据,我计算等级1,等级2。。。并将该评级添加到mysql_fetch_array()中已有的数组中。您知道,您也可以使用sql进行评级计算。不管怎样,看看我的答案,看看它是否适合你嗯,让我们说这是不可能的,就这样吧。我正在仔细考虑你的建议。提前感谢:)如果[id]是唯一的,您有什么理由不使用id作为数组键,而将其作为子数组中的字段?所以
array(1349=>array('rating1'=>…,'rating2'=>…),1350=>array…
我想比较每个
$data[]
的rating1,而不是每个
$data[][id]
!因此有三个
max
和三个相应的
id
s。这会找到在rating1或rating2ohhk中具有最大值的行,您可能还不清楚,我想单独在rating1中找到max。忽略rating2,现在我如何获得id?我已经单独提供了rating1,$max将等于匹配行,因此然后,您可以使用$max['id']来获取idI,因为它没有为任何数量的评级列提供完全通用的解决方案foreach(&$idx_max as$rating=>$max)正在生成错误,如果您想传递$idx_max作为引用,我认为$max应该替换为&$max,我尝试了,现在它可以工作了。太棒了!!非常好的代码和平。非常感谢,只是一个小问题,对于评级1,2,3,它返回5,4,4,即不是'id',但我可以轻松地处理$data[5]['id']要获取“id”的值,您已经修复了它,感谢您提供了这个极好的答案!为了提高效率,如果$data数组也通过引用传递会怎么样?它在任何地方都没有被修改…我不喜欢foreach语法,因为复制限制…我永远不知道要处理多少个数组。@sudhi:我已经注意到了这个id7分钟前修复的问题。感谢您指出引用运算符的错误位置。至于将数组本身作为引用传递:请自己尝试,很难说事先,但我认为不会有太多开销(写时复制?)嗯…写的时候拷贝,我总是忘记这一点,我的直觉告诉我不要创建你不会改变的东西的拷贝。PHP在这方面是非常不同的。无论如何,我没有时间和必要的技能来合理化引用传递和拷贝传递之间的区别,所以我会保持它的简单性,并遵循你所说的处方。非常感谢@knittl
$max = array_reduce($data, function($a, $b) {    
  if (is_null($a)) return $b;
  return $a['rating1']>$b['rating1'] ? $a : $b;
});
$ratingKeys=array_filter(array_keys($data[0]),function ($item) { return strstr($item,'rating')!==FALSE;});

$max = array_reduce($data,function($a,$b) use (&$ratingKeys) {
  if (is_null($a)) {
    $a=array();
    foreach($ratingKeys as $key) {
      $a[$key]=$b[$key];
      $a[$key.'_id'] = $b['id'];
     }
     return $a;
  }
  foreach($ratingKeys as $key) {
    if ($a[$key]<$b[$key]) {
      $a[$key]=$b[$key];
      $a[$key.'_id']=$b['id'];
    }
  }
  return $a;
});
array(4) {
  ["rating1"]=> float(0.0002788640872546)
  ["rating1_id"]=> int(1380)
  ["rating2"]=> float(2.2388295595073)
  ["rating2_id"]=> int(1379)
}
$max=array_reduce(array_keys($data),function ($a,$b) use (&$data) {
  if (is_null($a)) $a=array();
    foreach(array_keys($data[$b]) as $item) {
      if (!isset($a[$item]) {
        $a[$item] = $b;
      } else {
        if ($data[$a[$item]][$item]) < $data[$b][$item]) $a[$item]=$b;
      }
    return $a;
  }
});
array(2) {
  ["rating1"]=> int(1380)
  ["rating2"]=> int(1379)
}