我希望从数组中获取小于数值的子数组键 这是一个例子:
$arr_less_than = array(55,60,10,70);
$BlackList = array(10,8,15,20);
$MasterArray = array(
10 => array(1 => array(50,20,5,40), 2 => array(70,77,58,10), 3 => array(155,95,110,105), 4 => array(250,215,248,188)),
11 => array(1 => array(5,65,49,100), 2 => array(80,85,60,30), 3 => array(175,85,95,120), 4 => array(235,205,218,284)),
12 => array(1 => array(82,80,55,80), 2 => array(90,90,74,110), 3 => array(180,122,156,222), 4 => array(255,225,233,263)),
13 => array(1 => array(350,360,400,375), 2 => array(95,99,111,75), 3 => array(188,112,66,111), 4 => array(66,69,33,110)),
);
现在,如果子数组键不在数组$MasterArray
中,我需要从$arr_less_than
获得小于$BlackList
的子数组键。
对于上面的示例,结果必须返回array(12,13)
。
注意:我不想使用foreach循环
答案 0 :(得分:0)
这里有两个解决方案 - 一个用于所有子阵列符合标准,一个用于任何子阵列符合标准(这似乎是OP所考虑的)。最后,基于foreach
的解决方案适用于后一种情况,其中任何子阵列都符合标准。
如果我正确理解问题,目标是识别MasterArray中的行,其中所有子数组的值都大于$arr_less_than
中的对应值。
OP不想使用foreach(请参阅基于foreach
的答案的答案,这些答案更简单) - 这实际上可能会产生更高效的版本,因为它可以避免不必要的比较并保存一些周期,所以这里是一个使用数组函数的注释严重的版本。
我已经排除了可以从OP的帖子中复制的数据:
function getMatchingRows($arr_less_than, $MasterArray, $BlackList)
{
return array_values( // When we're done we just want a straight array of the keys from $MasterArray
array_filter(
array_keys($MasterArray), // Iterate over $MasterArray's keys (Because we need the keys for the BlackList)
function ($v) use ($BlackList, $MasterArray, $arr_less_than) {
// Filter out MasterArray Entries that dont meet the criteria
echo "Evaluate $MasterArray[$v]" . PHP_EOL;
// Remove array entries whose key is in the BlackList
if (in_array($v, $BlackList)) {
echo "\tBlacklisted" . PHP_EOL;
return false;
}
// For each entry in the MasterArray value, add up the number of non-matching entries
$y = array_reduce(
$MasterArray[$v],
function ($c1, $sub) use ($arr_less_than) {
// For each subarray entry in a MasterArray value, reduce the array to a count
// of elements whose value is less than the corresponding value in the $arr_less_than
$s1 = array_reduce(
array_keys($sub),
function ($carry, $key) use ($sub, $arr_less_than) {
if ($sub[$key] <= $arr_less_than[$key]) {
return ++$carry;
}
},
0 // Initial value for the array_reduce method
);
// $s1 will be a count of non-matching values
return $c1 + $s1;
},
0 //Initial value for the array_reduce method
);
echo "\t$y" . PHP_EOL;
// Include the array value in the filter only if there are no non-matching values ($y == 0)
return !$y;
}
)
);
}
print_r(getMatchingRows($arr_less_than, $MasterArray, $BlackList));
基本思想是从最外层的数组生成一个键列表 - 所以我们用array_filter迭代它们。然后我们在黑名单中排除那些带有密钥的那些。不在黑名单中的行通过迭代每个sub =数组值并将它们与$ arr_less_than进行正位数比较并将每个值加1而不是大于$ arr_less_than中的相应成员来减少为整数。然后将这些值汇总为MasterArray行中的所有成员。如果结果为零,则该行通过。最后,最终结果传递给array_values以规范化生成的数组。
请注意,这要求比较所有值,即使第一个子数组中的第一个子值失败也是如此。因此,可以逃避的foreach方法可能更有效。
这基本上是相同的方法,没有评论和几个快捷方式:
function getMatchingRows($arr_less_than, $MasterArray, $BlackList)
{
return array_values( // When we're done we just want a straight array of the keys from $MasterArray
array_filter(
array_keys($MasterArray),
function ($v) use ($BlackList, $MasterArray, $arr_less_than) {
return !in_array($v, $BlackList) && !array_reduce(
$MasterArray[$v],
function ($c1, $sub) use ($arr_less_than) {
return $c1 ?: array_reduce(
array_keys($sub),
function ($carry, $key) use ($sub, $arr_less_than) {
return $carry ?: ($sub[$key] <= $arr_less_than[$key] ? 1 : 0);
},
0
);
},
0
);
}
)
);
}
array_reduce中的一些方法使用?:运算符进行短路,因为实际计数是无关紧要的。一旦计数超过零,该行就会失败,无论如何。
如果标准是至少一个子阵列的所有成员都大于参考数组,则这是类似的代码。
function getMatchingRowsAny($arr_less_than, $MasterArray, $BlackList)
{
return array_values( // When we're done we just want a straight array of the keys from $MasterArray
array_filter(
array_keys($MasterArray), // Iterate over $MastrArray's keys (Because we need the keys for theBlackList)
function ($v) use ($BlackList, $MasterArray, $arr_less_than) {
// Filter out MasterArray Entries that dont meet the criteria
echo "Evaluate \MasterArray[$v]" . PHP_EOL;
// Remove array entries whose key is in the BlackList
if (in_array($v, $BlackList)) {
echo "\tBlacklisted" . PHP_EOL;
return false;
}
// For each entry in the MasterArray value, add up the number of non-matching entries
$y = array_reduce(
$MasterArray[$v],
function ($c1, $sub) use ($arr_less_than) {
// For each subarray entry in a MasterArray value, reduce the array to a flag
// indicating if it has whose value is <= the corresponding value in the $arr_less_than
$s1 = array_reduce(
array_keys($sub),
function ($fail, $key) use ($sub, $arr_less_than) {
return $fail || $sub[$key] <= $arr_less_than[$key];
},
false
);
// This could be short-circuited above to avoid an unnecessary array_reduce call
return $c1 || !$s1;
},
false
);
echo "\t$y" . PHP_EOL;
// Include the array value in the filter if there are any matching values
return $y;
}
)
);
}
print_r(getMatchingRowsAny($arr_less_than, $MasterArray, $BlackList));
作为一个练习(因为我是贪婪的惩罚)我使用foreach
作为生成器和返回数组的函数呈现相同的方法 - 主要是为了说明foreach可能是更好的选择,肯定更简单:
// Implemented as a generator - The associated foreach that uses it follows
function generateMatchingRows($arr_less_than, $MasterArray, $BlackList)
{
foreach ($MasterArray as $k => $v) {
if (in_array($k, $BlackList)) {
continue;
}
foreach ($v as $sub_array) {
$match = true;
foreach ($sub_array as $k1 => $v1) {
if ($v1 <= $arr_less_than[$k1]) {
$match = false;
break;
}
}
if ($match) {
yield $k;
break;
}
}
}
}
foreach (generateMatchingRows($arr_less_than, $MasterArray, $BlackList) as $k) {
echo $k . PHP_EOL; // Or push them onto an array
}
// Implemented as a function returning an array - classical approach - just return an array
function getMatchingRowsForEach($arr_less_than, $MasterArray, $BlackList)
{
$rv = [];
foreach ($MasterArray as $k => $v) {
if (in_array($k, $BlackList)) {
continue;
}
foreach ($v as $sub_array) {
$match = true;
foreach ($sub_array as $k1 => $v1) {
if ($v1 <= $arr_less_than[$k1]) {
$match = false;
break;
}
}
if ($match) {
$rv[] = $k;
break;
}
}
}
return $rv;
}
print_r(getMatchingRowsForEach($arr_less_than, $MasterArray, $BlackList));