You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中如何高效排除range中的指定间隔数?

无大列表的范围数字过滤高效实现

针对你提出的三个场景,这里给出无需创建大型列表、内存友好的高效方案:

1. 从range中排除每第n个数字(例:1-100排除第3个)

如果是排除位置上的第n个、第2n个...(比如1-100里的第3、6、9位数字),用生成器跟踪位置即可;如果是排除数值为n的倍数,推荐用拼接range的方式,完全惰性求值,无额外内存消耗:

方案一:生成器(灵活通用)

def exclude_every_nth(start, end, n):
    for idx, num in enumerate(range(start, end+1), start=1):
        if idx % n != 0:
            yield num

# 调用示例:1-100排除每第3个数字
for num in exclude_every_nth(1, 100, 3):
    print(num)

如果要排除数值本身是n的倍数,把判断条件改成num % n != 0即可。

方案二:拼接range(超大范围更高效)

利用range的惰性特性,直接生成连续的有效区间,完全不需要循环判断:

def exclude_multiples(start, end, n):
    # 处理开头的不完整块
    first_block_end = min(start + n - 1, end)
    yield from range(start, first_block_end + 1)
    
    # 循环生成后续的完整块(每个块跳过一个n的倍数)
    current = first_block_end + 1
    while current <= end:
        block_end = min(current + n - 1, end)
        yield from range(current, block_end + 1)
        current += n

# 调用示例:1-100排除3的倍数
for num in exclude_multiples(1, 100, 3):
    print(num)

2. 排除多个间隔数(例:同时排除第3和第11个)

本质是排除多个数的倍数,分两种场景选择方案:

方案一:生成器+多条件判断(简单直观,适合少量倍数)

def exclude_multi_multiples(start, end, multiples):
    for num in range(start, end+1):
        # 仅保留不被任何指定倍数整除的数
        if not any(num % m == 0 for m in multiples):
            yield num

# 调用示例:1-100排除3和11的倍数
for num in exclude_multi_multiples(1, 100, [3, 11]):
    print(num)

方案二:容斥原理拼接range(超大范围高效)

如果范围极大,不想做任何取模运算,用容斥原理生成所有有效区间(以两个倍数为例,多倍数可扩展逻辑):

import math
import itertools

def exclude_multiples_large_range(start, end, multiples):
    m1, m2 = multiples
    lcm = m1 * m2 // math.gcd(m1, m2)  # 最小公倍数
    template = [x for x in range(1, lcm+1) if x % m1 != 0 and x % m2 != 0]
    
    # 计算第一个周期的起始点
    start_cycle = ((start - 1) // lcm) * lcm + 1
    current = start_cycle
    
    while current <= end:
        offset = current - 1
        for num in template:
            val = offset + num
            if val > end:
                break
            if val >= start:
                yield val
        current += lcm

# 调用示例:1-1000000排除3和11的倍数
for num in exclude_multiples_large_range(1, 10**6, [3, 11]):
    pass

3. 超大范围排除能被3整除的数(替代取模的高效方案)

最极致的高效方式是直接拼接连续的有效range,完全没有取模运算,内存占用为O(1):

import itertools

def exclude_divisible_by_3(start, end):
    ranges = []
    # 处理开头的不完整块
    first_excluded = ((start + 2) // 3) * 3
    if start < first_excluded:
        ranges.append(range(start, first_excluded))
    
    # 生成中间的完整块(每个块包含2个连续数,跳过1个3的倍数)
    current = first_excluded
    while current + 2 <= end:
        ranges.append(range(current + 1, current + 3))
        current += 3
    
    # 处理结尾的不完整块
    if current + 1 <= end:
        ranges.append(range(current + 1, end + 1))
    
    # 拼接所有range并返回
    yield from itertools.chain(*ranges)

# 调用示例:1到1亿的范围内排除3的倍数
for num in exclude_divisible_by_3(1, 10**8):
    # 处理每个数,无内存压力
    pass

这个方案利用range的底层优化,所有操作都是数学计算,效率远高于逐个取模。


内容的提问来源于stack exchange,提问作者Jonas David

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 22:35:39