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