我有阵列:
$arr1 = array(5, 3, 9, 11, 6, 15);
$arr2 = array(11, 20, 1, 3, 8);
现在我需要遍历$arr1
并找到小于X
的最大数字:
foreach($arr1 as $x) {
//need element that is MAX in $arr2 but is less than $x
}
例如,$x = 5
时的第一次投放,$arr2
中的最大值 3 小于 5 。
是否可以在没有嵌套循环的情况下执行此操作?我不想循环遍历$arr2
。我尝试使用array_filter
,但没有真正起作用。也许我用错了。
这是我尝试使用array_filter
:
$results = array();
foreach($arr1 as $x) {
$max = max(array_filter($arr2, function ($x) { return $x < $y; }));
$results[$x] = $max;
}
结果应该是这样的:
5 => 3,
3 => 1,
9 => 8,
11 => 8,
6 => 3,
15 => 11
答案 0 :(得分:11)
问题在于使用lambda - PHP not 会自动捕获封闭范围内的变量。 (官方Anonymous Functions在该主题上有点稀疏,因此请参阅In PHP 5.3.0, what is the function "use" identifier?。)
比较原始数据,它返回一个空数组,因为它实际上是$x < undefined
$arr2 = array(11, 20, 1, 3, 8);
$y = 5;
var_dump(array_filter($arr2, function ($x) { return $x < $y; }));
以下使用use
语法绑定函数中的变量
$arr2 = array(11, 20, 1, 3, 8);
$y = 5;
var_dump(array_filter($arr2, function ($x) use ($y) { return $x < $y; }));
(另外,在原始代码中根本没有$ y变量,哎呀!)
答案 1 :(得分:4)
这是一种方法,使用array_map()
返回低于最大变量的值,然后使用max()
返回最高值(如示例所示)。
在此示例中,我使用$var
作为variable by reference (the &
),以便get_highest()
回调函数可以使用它作为全局变量访问它。
function get_highest($x) {
global $var;
return $x < $var ? $x : 0;
}
$results = array();
foreach($arr1 as &$var) {
$results[$var] = max(array_map('get_highest', $arr2));
}
如果您不想通过将参数数组传递给array_map()
来使用全局变量,则可以修改此项。它的工作方式有点奇怪,因为参数数组需要与原始数组的长度相同,所以我使用array_fill()
将当前值填充到所需的长度,因此回调函数可以用来比较:
function get_highest($x, $y) {
return $x < $y ? $x : 0;
}
$results = array();
foreach($arr1 as $var) {
$max = array_fill(0, count($arr2), $var);
$results[$var] = max(array_map('get_highest', $arr2, $max));
}
答案 2 :(得分:2)
重用/重置 arr2
的任何解决方案将具有二次复杂性,这意味着如果你有一个大小为N的arr1和一个大小为M的arr2,你将会是做N * M操作。
在lambda函数的情况下,函数调用和参数传递。
如果N和M非常大,则更好的策略是对两个数组进行排序(复杂度为N log N + M log M),然后使用与合并排序相同的策略来循环遍历数组,从而保存其状态。这将在大多数N + M操作中执行而不是N * M,从而使整体复杂度linearithmic。
lambda解决方案更容易理解,更强大,更易于维护,因此除非出现紧迫的原因(成千上万的N和M),否则首选。您的交易速度便于维护;但这通常是一个甜蜜的交易。
首先,使用PHP的数组排序函数对两个数组进行排序,然后获取
$arr1 = array(3, 5, 6, 9, 11, 15);
$arr2 = array(1, 3, 8, 11, 20);
$map = array();
$n = count($arr1);
$m = count($arr2);
for ($i = 0, $j = 0, $y = false; $i < $n;) {
if ($j == $m) {
$map[$arr1[$i++]] = $y;
} else {
if ($arr1[$i] <= $arr2[$j]) {
$map[$arr1[$i++]] = $y;
} else {
$y = $arr2[$j++];
}
}
}