获取数组列中的最小值和最大值
Posted
技术标签:
【中文标题】获取数组列中的最小值和最大值【英文标题】:Get the minimum and maximum values in an array column 【发布时间】:2010-11-23 15:17:54 【问题描述】:我有一个这种格式的数组:
$array = [
['id' => 117, 'name' => 'Networking', 'count' => 16],
['id' => 188, 'name' => 'FTP', 'count' => 23],
['id' => 189, 'name' => 'Internet', 'count' => 48],
];
有没有很好的方法来检索“计数”列的最小值和最大值(分别为16
和48
)?
我可以使用几个循环来做到这一点,但我想知道是否有更好的方法。
【问题讨论】:
+1 我今天遇到了这个问题,我只是做了一个循环。好奇还有什么其他方法。 如果有一些函数可以做到这一点,它将通过循环实现,那么使用你自己的函数有什么不好?! @Svetlozar Angelov:对于 php 函数,循环将用 C 而非 PHP 编写,因此它们通常更快。 【参考方案1】:与其他人发布的相比,您不能使用min()
/max()
函数解决此问题,因为这些函数不理解传入的数据结构(数组)。这些函数仅适用于标量数组元素。
开始编辑
使用min()
和max()
似乎产生正确答案的原因与将数组类型转换为整数有关,即undefined behaviour:
转换为整数的行为 对于其他类型未定义。不要 依赖于任何观察到的行为,因为它 如有更改,恕不另行通知。
我上面关于类型转换的陈述是错误的。实际上 min()
和 max()
确实可以使用数组,但不是 OP 需要它们工作的方式。将min()
和max()
与多个数组或数组元素一起使用时,从左到右逐个元素进行比较:
$val = min(array(2, 4, 8), array(2, 5, 1)); // array(2, 4, 8)
/*
* first element compared to first element: 2 == 2
* second element compared to second element: 4 < 5
* first array is considered the min and is returned
*/
转化为 OP 的问题,这说明了直接使用 min()
和 max()
似乎会产生正确结果的原因。数组的第一个元素是id
-values,因此min()
和max()
将首先比较它们,顺便说一句,导致正确的结果,因为最低的id
是最低count
和最高的id
是count
最高的一个。
结束编辑
正确的方法是使用循环。
$a = array(
array('id' => 117, 'name' => 'Networking', 'count' => 16),
array('id' => 188, 'name' => 'FTP', 'count' => 23),
array('id' => 189, 'name' => 'Internet', 'count' => 48)
);
$min = PHP_INT_MAX;
$max = 0;
foreach ($a as $i)
$min = min($min, $i['count']);
$max = max($max, $i['count']);
【讨论】:
来自 max$val = max(array(2, 4, 8), array(2, 5, 7)); // array(2, 5, 7)
的手册页。阅读它。
您的答案是正确的,但不是因为您所说的原因。 min
和 max
正确处理数组并且不要将它们转换为整数,手册提供了更多详细信息。
@MitMaro:你是对的——我对在 min() 和 max() 中使用数组的假设或推理是错误的。我编辑了我的答案并删除了错误的陈述。
作为“锡箔帽”参数,如果输入数组为空,这个答案将返回不正确的结果。当然,我不知道 OP 的应用程序是否可以传入一个空数组。这只是对研究人员的警告。【参考方案2】:
您可以使用max() 和min() 函数。
【讨论】:
这充其量只是部分答案。【参考方案3】:你用几个循环做了什么?一个就够了:)
-
获取第一个元素,将计数分配给 $min 和 $max
遍历其余部分,将 count 与每个 $min 和 $max 进行比较,如果更小/更大,则分配新的 count 值
【讨论】:
这似乎解释得很好,但是如果没有 sn-p,研究人员可能无法按照您的意图实施您的建议。您可能会或可能不会在我的回答中认可第一个 sn-p。如果你有不同的看法,也许在你的答案中添加一个 sn-p 并解释你为什么会以你独特的方式去做。【参考方案4】:看起来你不能在二维数组上使用 max()。它只返回最大的数组,而不是每个索引的 max() (如几个答案中所述)。
所以:
$count = array();
foreach($arr as $_arr)
$count[] = $_arr['count'];
var_dump(max($count), min($count));
【讨论】:
【参考方案5】:如果所需的列是数组中的第一个,您可以使用以下单行:
$max = max(array_map('current', $a));
$min = min(array_map('current', $a));
这将找到 id
的最小值/最大值【讨论】:
为什么要调用array_map()
两次以获得相同的返回值?这缺乏效率,也不是 D.R.Y.【参考方案6】:
从前面的答案中可以看出,有许多可行的技术可供考虑。
如果您正在考虑最佳性能,那么您应该尽量减少使用的循环数和函数调用数。
“在幕后”,本机函数 min()
和 max()
将完全迭代它们所提供的数组。因此,如果您使用函数或构造循环遍历二维输入数组,然后调用min()
,然后调用max()
,您将分别迭代输入数组的完整长度三次。
考虑这个只迭代 1 次的 sn-p:
代码:(Demo)
$min = array_shift($array)['count'] ?? null;
$max = $min;
foreach ($array as $row)
if ($min > $row['count'])
$min = $row['count'];
if ($max < $row['count'])
$max = $row['count'];
var_export(['min' => $min, 'max' => $max]);
以上的优点是
只有 1 个函数调用(用于提取第一行的数据)和一个循环
它不会多次遇到相同的数据
简单的数值比较对于 php 来说执行起来非常简单/快速
以上的缺点是
它通过调用array_shift()
来改变输入数组,所以如果你在同一个范围内重复使用这个数组,它将不再包含第一个值
它比其他一些技术更冗长,并且忽略了一些可行的原生函数
另一种技术重视功能样式的代码。 PHP 有本机函数,可以轻松完成这项任务。
array_column()
可以隔离count
列中的所有值。
min()
返回最小的数字。
max()
返回最大的数字。
代码:(Demo)
$counts = array_column($array, 'count');
var_export(['min' => min($counts), 'max' => max($counts)]);
以上的优点是
只有 1 个临时变量
它不会改变输入数组
非常简洁、直观和声明式的编码风格
如果其中一行缺少count
元素,它不会生成任何警告
以上的缺点是
从技术上讲,它会迭代数据 3 次
它的性能很可能比第一个 sn-p 差
【讨论】:
【参考方案7】:是否有与之等效的内置功能? (即使没有 test 能力)
/** * 从二维数组中提取一列,可选择另一列 * * @param $aArray 要从中提取的数组 * @param $aColName 要提取的列的名称,例如。 'O_NAME' * @param $aColTest(可选)进行测试的列的名称,例如。 'O_ID' * @param $aTest (可选) 测试字符串。 ">= 10", "=='".$toto."'" * @return 仅包含提取列的一维数组 * @访问公共 */ 函数 extractColFromArray($aArray, $aColName, $aColTest="", $aTest="") $mRes = 数组(); foreach($aArray as $row) if (($aColTest == "") || (eval("return " . $row[$aColTest] . $aTest . ";" )) ) $mRes[] = $row[$aColName]; 返回$mRes; // extractColFromArray【讨论】:
这个 sn-p 在 2-dim 数组中找不到最小值和最大值。这不是这个问题的正确答案。以上是关于获取数组列中的最小值和最大值的主要内容,如果未能解决你的问题,请参考以下文章
sql MIN()和MAX()允许您从表中的列中提取最小值和最大值。第1行显示MIN()示例,它选择最小值
从具有 O(n) 的数组中获取最大的时间下降、最小值和最大值