4 回答

TA貢獻1811條經驗 獲得超6個贊
您可以通過在 $ranges 數組的開頭和結尾添加限制值來簡化邏輯,然后只需成對處理整個數組。
<?php
$ranges = [10,15,30];
$values = [1,4,12,15,27,32];
\array_push($ranges, null); // append null to array
\array_unshift($ranges, null); // prepend null to array
$output = [];
$count = \count($ranges);
for ($i = 0; $i < $count - 1; $i++) {
$output[] = ['start' => $ranges[$i], 'end' => $ranges[$i+1], 'count' => 0];
}
foreach ($values as $value) {
foreach ($output as $key => $range) {
if (
($range['start'] === null || $range['start'] <= $value) &&
($range['end'] === null || $range['end'] > $value)
) {
$output[$key]['count']++;
break;
}
}
}
var_dump($output);

TA貢獻1898條經驗 獲得超8個贊
$ranges首先使用數組中的鍵(使用)創建一個歸零數組array_fill_keys(),再加上一個用于“超過”最后一個條目的值。
循環遍歷每個值并根據范圍檢查它,如果找到它,它只會將相應的計數加 1 并停止查找。如果在完成循環后,該值大于最后一個范圍,則將 1 添加到“over”條目。
$ranges = array(10,15,30);
$values = array(1,4,12,15,27,32);
$rangeCount = array_fill_keys($ranges, 0);
$rangeCount[ "over" ] = 0;
foreach ( $values as $value ) {
foreach ( $ranges as $range ) {
if ( $value < $range ) {
$rangeCount [ $range ]++;
break;
}
}
if ( $value >= $range ) {
$rangeCount[ "over" ]++;
}
}
print_r($rangeCount);
這使...
Array
(
[10] => 2
[15] => 1
[30] => 2
[over] => 1
)
只是為了添加一個只做一個循環的優化版本。但假設這些值是按升序排列的。每次它通過“當前”范圍時,它都會移動到下一個輸出計數器,最后一部分甚至不會循環超過最大值,它會從總計數中減去當前計數并中斷...
$currentRange = 0;
$numberValues = count($values);
$numberRanges = count($ranges);
$rangeCount = array_fill(0, $numberRanges, 0);
$rangeCount[ "over" ] = 0;
foreach ( $values as $count => $value ) {
if ( $value >= $ranges[$currentRange] ) {
$currentRange++;
if ( $currentRange >= $numberRanges ) {
$rangeCount[ "over" ] = $numberValues - $count;
break;
}
}
$rangeCount[$currentRange]++;
}
print_r($rangeCount);

TA貢獻1802條經驗 獲得超6個贊
以下解決方案首先按升序/非降序對范圍進行排序。
然后,我們創建一個range_map它是所有可能范圍的集合$ranges。
然后,我們遍歷所有值$values并進行二進制搜索以$ranges獲得特定值所屬的確切范圍索引。在下面的代碼中,精確索引存儲在$low.
然后,我們只需通過取范圍鍵$range_map并將其計數器加 1 來收集計數。
這比嵌套循環更快,因為嵌套循環的時間復雜度O(m*n)是m大小$ranges和n大小$values,而當前解決方案的時間復雜度O(m logm) + O(n logm)是m大小$ranges和n大小$values。
片段:
<?php
$ranges = array(10,15,30);
$values = array(1,4,12,15,27,32);
sort($ranges);
$range_map = [];
$ptr = 0;
foreach($ranges as $index => $value){
if($index === 0) $range_map[$ptr++] = "<" . $value;
if($index > 0) $range_map[$ptr++] = $ranges[$index - 1] . "-" . $value;
if($index === count($ranges) - 1) $range_map[$ptr++] = ">=" . $value;
}
$result = [];
foreach($values as $value){
$low = 0; $high = count($ranges) - 1;
while($low <= $high){
$mid = $low + intval(($high - $low) / 2);
if($value === $ranges[ $mid ]){
$low = $mid + 1;
break;
}else if($value < $ranges[ $mid ]){
$high = $mid - 1;
}else{
$low = $mid + 1;
}
}
if(!isset($result[$range_map[$low]])) $result[$range_map[$low]] = 0; // get the range key from range_map
$result[$range_map[$low]]++; // increment the value for that range
}
print_r($result);
演示: https ://3v4l.org/JcYBv

TA貢獻1776條經驗 獲得超12個贊
假設您有預先排序的范圍和值。
<?php
$ranges = array(10,15,30);
$values = array(1,4,12,15,27,32);
$lower = null;
$i = 0;
$upper = $ranges[$i];
foreach($values as $item) {
if(!is_null($upper) && $item >= $upper) {
$lower = $upper;
$upper = $ranges[++$i] ?? null;
}
$result["$lower<$upper"][] = $item;
}
var_export(array_map('count', $result));
輸出:
array (
'<10' => 2,
'10<15' => 1,
'15<30' => 2,
'30<' => 1,
)
- 4 回答
- 0 關注
- 155 瀏覽
添加回答
舉報