【问题标题】:php find max in 2 dimension array but return another element('id') of the arrayphp在二维数组中找到最大值,但返回数组的另一个元素('id')
【发布时间】:2011-08-05 12:49:20
【问题描述】:

这是我的数组样本$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_rating?],即与max 值关联的id
找到一个特定的最大值很容易,比如rating1,我使用array_reduce 如下(灵感来自this SO):

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

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

我不太关心 Q1,但第二个很重要,因为我不想再次搜索数组以获取关联 $data[][id]
一种思路是使用array_map 而不是array_reduce,但我想不出一个可以同时传递[id][rating?] 的版本。此外,当我尝试同时max() 多个rating? 时也会出现问题,因为每个评分都会有不同的max,而这又会与不同的[id] 相关联。
编辑:为了清楚起见,我希望所有各自的 ids 与每个 rating? 的各自 max 相关联

【问题讨论】:

  • 这看起来像数据库中的表。如果是这样,请在数据库级别进行过滤!
  • 不,这不是,根据表中的数据,我计算 rating1,rating2... 并将该评分添加到 mysql_fetch_array() 已经可用的数组中。
  • 你也可以在 sql 中进行评分计算,你知道的。无论如何,看看我的答案,看看它是否适合你
  • 嗯,让我们说不可能,然后就这样吧。我正在考虑你的建议。在此先感谢:)
  • 如果 [id] 是唯一的,是否有任何理由不使用 id 作为数组键而不是将其作为子数组中的字段?所以array(1349 => array ('rating1'=>....,'rating2'=>....),1350=> array.....

标签: php multidimensional-array mapreduce max


【解决方案1】:

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

$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 本身设为一个数组并添加更多 if):

$idx_max = array (
  'sudhi_rating1' => 0,
  'sudhi_rating2' => 0,
  /* … */ );
foreach($array as $idx => $item) {
  foreach($idx_max as $rating => &$max) {
    if($item[$rating] > $array[$max][$rating])
      $max = $idx;
  }
}

foreach($idx_max as $rating => $max)
  echo 'Max value for ', htmlspecialchars($rating), ' has id ', htmlspeciachars($array[$max]['id']);

【讨论】:

  • foreach(&$idx_max as $rating => $max) 正在生成错误,如果你想传递 $idx_max 作为参考,我认为 $max 应该替换为 &$max ,我试过了现在可以了。极好 !!极好的代码和平。非常感谢,只是一个小问题,它为 rating1,2,3 返回 5,4,4,即不是 'id',但我可以轻松地 $data[5]['id'] 来获取 'id' 的值'。
  • 您已修复,感谢您的出色回答!只是为了提高效率,如果 $data 数组也是通过引用传递呢?它没有在任何地方修改...由于复制限制,我不喜欢 foreach 语法...我永远不知道我将需要处理多少个数千个数组。
  • @sudhi:我已经注意到 7 分钟前修复的 id 问题。感谢您指出参考运算符的错误位置。至于将数组本身作为参考传递:自己尝试,很难事先说,但我认为不会有太多开销(写时复制?)
  • 嗯...写时复制,我总是忘记这一点,我的直觉告诉我不要创建你不会改变的东西的副本。 PHP 在这方面非常不同。无论如何,我没有时间和必要的技能来合理化通过引用传递和通过副本传递之间的区别,所以我会保持简单并遵循你的规定。非常感谢@knittl
【解决方案2】:
$max = array_reduce($data, function($a, $b) {    
  if (is_null($a)) return $b;
  return max($a['rating1'],$a['rating2'])>max($b['rating1'],$b['rating2']) ? $a : $b;
});

结果:没有条目 $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;
});

这段代码导致

array(4) {
  ["rating1"]=> float(0.0002788640872546)
  ["rating1_id"]=> int(1380)
  ["rating2"]=> float(2.2388295595073)
  ["rating2_id"]=> int(1379)
}

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

这段代码导致

array(2) {
  ["rating1"]=> int(1380)
  ["rating2"]=> int(1379)
}

【讨论】:

  • 我想比较每个 $data[] 的 rating1 而不是每个 $data[][id] 之间的比较!所以有三个max和三个对应的ids
  • 这会找到在 rating1 或 rating2 中具有最大值的行
  • ohhk,也许你还不清楚,我想单独在 rating1 中找到 max。忽略 rating2,现在我怎样才能获得 id?
  • 我单独提供了 rating1,$max 将等于匹配行,因此您可以使用 $max['id'] 获取 id
  • 我没有为任意数量的评级列提供一个完全通用的解决方案
猜你喜欢
  • 1970-01-01
  • 2022-11-13
  • 2016-04-14
  • 2021-02-18
  • 1970-01-01
  • 2021-06-14
  • 2014-09-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多