如何在R语言中寻找互补的连续整数区间?
生成互补连续区间的方法
不管你是用列表还是tibble存储原区间,核心思路都是:先确定目标范围的所有整数,找出原区间未覆盖的补集整数,再将这些零散整数合并为连续区间。
1. 处理列表形式的区间
假设你有如下列表形式的原区间,目标范围是1-20:
intervals <- list(3:6, 10:11, 19:20) full_range <- 1:20
按以下步骤操作:
- 合并原区间的所有整数为一个向量:
original_nums <- unlist(intervals) - 计算目标范围内不在原区间的补集整数:
complement_nums <- setdiff(full_range, original_nums) - 将补集整数转换为连续区间列表:
# 通过diff判断连续性,cumsum生成分组ID,再按分组生成区间 complementary_intervals <- lapply( split(complement_nums, cumsum(c(1, diff(complement_nums) != 1))), function(group) min(group):max(group) )
运行后complementary_intervals就是你需要的list(1:2, 7:9, 12:18)。
2. 处理tibble/dataframe形式的区间
如果你用tibble存储区间(需要加载tidyverse):
library(tidyverse) intervals <- tribble( ~start, ~end, 3, 6, 10, 11, 19, 20 ) full_range <- 1:20
用tidyverse工具链实现:
- 先展开原区间的所有整数:
original_nums <- unlist(map2(intervals$start, intervals$end, seq)) - 计算补集并转换为tibble格式的互补区间:
complement_intervals_df <- complement_nums %>% tibble(num = .) %>% # 给每个连续整数段分配唯一分组ID mutate(group_id = cumsum(c(1, diff(num) != 1))) %>% group_by(group_id) %>% summarise(start = min(num), end = max(num)) %>% ungroup() %>% select(-group_id)
运行后得到的tibble如下:
# A tibble: 3 × 2 start end <int> <int> 1 1 2 2 7 9 3 12 18
关键逻辑说明
diff(complement_nums) != 1可以检测整数是否连续:相邻两数差不为1时,说明是连续段的分界点。cumsum(c(1, diff(...) !=1))会给每个连续段生成唯一的分组ID,后续按分组取最小/最大值就能得到区间的起止。
如果原区间覆盖了整个目标范围,补集会是空向量,最终结果也会是空列表或空tibble,无需额外处理。
内容的提问来源于stack exchange,提问作者jsavn
相关产品推荐
相关产品推荐

