PHP中数字范围的计算
首先,感谢您抽出时间阅读我的问题 我试图写一个脚本,我遇到了一个我发现很难解决的问题。我正在处理一对数字,例如1000和2000,我有一个数字对数组:PHP中数字范围的计算,php,arrays,range,integer,Php,Arrays,Range,Integer,首先,感谢您抽出时间阅读我的问题 我试图写一个脚本,我遇到了一个我发现很难解决的问题。我正在处理一对数字,例如1000和2000,我有一个数字对数组: $pairs = array( array(800, 1100), array(1500, 1600), array(1900, 2100) ) 我试图找到的是,如何得到数字对未覆盖的范围,介于1000和2000之间。在本例中,1000-1100由阵列800覆盖,1100、1500-1600由阵列1500、1600覆盖,
$pairs = array(
array(800, 1100),
array(1500, 1600),
array(1900, 2100)
)
我试图找到的是,如何得到数字对未覆盖的范围,介于1000和2000之间。在本例中,1000-1100由阵列800覆盖,1100、1500-1600由阵列1500、1600覆盖,1900-2000由阵列1900、2100覆盖,剩下1101-1499和1599-1899要覆盖。我希望我说得够清楚了
我想知道的是如何让PHP返回给我一个$pairs变量未包含的范围数组。在本例中,它将返回:
array(
array(1101, 1499),
array(1599, 1899)
)
你知道什么是最好的方法吗
提前谢谢你。我会这样做:
begin = 1000
end = 2000
uncovered = ()
foreach pairs as pair
if (pair[0] > begin)
push (uncovered, begin, pair[0])
begin = pair[1]
end if
end foreach
这只是一个想法,但关键是:
假设你有一个从1000到2000的小片段。你想得到大的一个没有被小的一个覆盖的每一个部分。想象你有一支钢笔
从头开始。迭代你拥有的每个小片段。如果你严格地在开始之后,那么就有一个洞,所以你必须记住从开始到当前片段的开始
希望这有帮助,这是正确的 首先,您必须定义问题: 这两对是按顺序排列的吗? 成对重叠吗? 您想查找特定范围的缺失范围似乎是这样吗? 如果对未排序,请首先对其进行排序:
usort($pairs, 'cmp_pair');
function cmp_pair($a, $b) {
if ($a[0] == $b[0]) {
if ($a[1] == $b[1]) {
return 0;
} else {
return $a[1] < $b[1] ? -1 : 1;
}
} else {
return $a[0] < $b[0] ? -1 : 1;
}
}
现在不应该有任何重叠对,所以问题变得简单了一点,因为您还得到了一个排序数组
function missing($start, $end, $pairs) {
$missing = array();
$prev = false;
foreach ($pairs as $pair) {
// if the current pair starts above the end, we're done
if ($pair[0] > $end) {
break;
}
// we can ignore any pairs that end before the start
if ($pair[1] < $start) {
continue;
}
// if the pair encompasses the whole range, nothing is missing
if ($pair[0] <= $start && $pair[1] >= $end) {
break;
}
// if this is our first overlapping pair and it starts above
// the start we can backfill the missing range
if ($pair[0] > $start && !$missing) {
$missing[] = array($start, $pair[0]);
}
// compare this pair to the previous one (if there is one) and
// fill in the missing range
if ($prev) {
$missing[] = array($prev[1]+1, $pair[0]-1);
}
// set the previous
$prev = $pair;
}
// if this never got set the whole range is missing
if (!$prev) {
$missing[] = array($start, $end);
// if the last overlapping range ended before the end then
// we are missing a range from the end of it to the end of
// of the relevant range
} else if ($prev[1] < $end) {
$missing[] = array($prev[1]+1, $end);
}
// done!
return $missing;
}
希望有帮助
// your original arrays of integers
$pairs = array(
array(800, 1100),
array(1500, 1600),
array(1900, 2100)
);
// first, normalize the whole thing into a giant list of integers that
// are included in the array pairs, combine and sort numerically
$numbers_in_pairs = array();
foreach($pairs as $set) {
$numbers_in_pairs = array_merge($numbers_in_pairs, range($set[0], $set[1]));
}
sort($numbers_in_pairs);
// find the min
$min = $numbers_in_pairs[0];
// find the max
$max = $numbers_in_pairs[count($numbers_in_pairs)-1];
找出数组的差异
关于我们稍后将使用的集合的元数据:
结果:
这个答案对我来说非常有效,谢谢你:我唯一需要更正的是如果$prev。。。如果$pair[0}>$start&&!$missing,则应该在前面,因为对于800-1100,函数只设置$prev,这意味着当它到达第二对时,它仍然认为它是第一对,因此1000-1500之间的所有内容都被视为丢失。非常感谢您的帮助,cletus:
// your original arrays of integers
$pairs = array(
array(800, 1100),
array(1500, 1600),
array(1900, 2100)
);
// first, normalize the whole thing into a giant list of integers that
// are included in the array pairs, combine and sort numerically
$numbers_in_pairs = array();
foreach($pairs as $set) {
$numbers_in_pairs = array_merge($numbers_in_pairs, range($set[0], $set[1]));
}
sort($numbers_in_pairs);
// find the min
$min = $numbers_in_pairs[0];
// find the max
$max = $numbers_in_pairs[count($numbers_in_pairs)-1];
// create an array of all numbers inclusive between the min and max
$all_numbers = range($min, $max);
// the numbers NOT included in the set can be found by doing array_diff
// between the two arrays, we need to sort this to assure no errors when
// we iterate over it to get the maxes and mins
$not_in_set = array_diff($all_numbers, $numbers_in_pairs);
sort($not_in_set);
// gather metadata about the numbers that are not inside the set
// $not_in_set_meta['min'] = lowest integer
// $not_in_set_meta['max'] = highest integer
// $not_in_set_meta['mins'] = min boundary integer
// $not_in_set_meta['maxes'] = max boundary integer
$not_in_set_meta = array();
for($i=0;$i<count($not_in_set);$i++) {
if ($i == 0) {
$not_in_set_meta['min'] = $not_in_set[$i];
$not_in_set_meta['mins'][] = $not_in_set[$i];
} else if ($i == count($not_in_set)-1 ) {
$not_in_set_meta['max'] = $not_in_set[$i];
$not_in_set_meta['maxes'][] = $not_in_set[$i];
} else {
// in the event that a number stands alone
// that it can be BOTH the min and the max
if (($not_in_set[$i+1] - $not_in_set[$i]) > 1) {
$not_in_set_meta['maxes'][] = $not_in_set[$i];
}
if (($not_in_set[$i] - $not_in_set[$i-1]) > 1) {
$not_in_set_meta['mins'][] = $not_in_set[$i];
}
}
}
// The final variable which we'll dump the ranges not covered into:
$non_sets = array();
while(count($not_in_set_meta['mins']) > 0 && count($not_in_set_meta['maxes'])) {
$non_sets[] = array(array_shift($not_in_set_meta['mins']),
array_shift($not_in_set_meta['maxes']));
}
// print it out:
print var_export($non_sets);
array (
0 =>
array (
0 => 1101,
1 => 1499,
),
1 =>
array (
0 => 1601,
1 => 1899,
),
)
?>