Python 查找不在间隔列表中的最小数字

Python 查找不在间隔列表中的最小数字,python,intervals,Python,Intervals,我必须找到不在间隔列表中的最小数字。例如,我有一个列表:[(2,6),(0,3),(9,10)]。我必须通过检查从0到10的所有数字来找到最小的数字,直到找到不在这些范围内的最小数字。 因此,数字不能介于2和6(包括两者)、0和3、9和10之间 我写了一个函数,但我不能得到正确的答案。我总是得到程序检查的所有第一个数字,但我只需要最后一个。 我不明白为什么它不适用于return intervals = [(2, 6), (0, 3), (9, 10)] def smallest_number(i

我必须找到不在间隔列表中的最小数字。例如,我有一个列表:[(2,6),(0,3),(9,10)]。我必须通过检查从0到10的所有数字来找到最小的数字,直到找到不在这些范围内的最小数字。 因此,数字不能介于2和6(包括两者)、0和3、9和10之间

我写了一个函数,但我不能得到正确的答案。我总是得到程序检查的所有第一个数字,但我只需要最后一个。 我不明白为什么它不适用于return

intervals = [(2, 6), (0, 3), (9, 10)]
def smallest_number(intervals):
   i = 0
   while True:
      for first, second in intervals:
         if i in range(first, second + 1):
            i += 1
            print(i)

print(smallest_number(intervals))

我希望输出为7,但我得到一个7或1到7之间的数字循环,这取决于我在哪里放置print(I)。

这里有一种方法:

from itertools import chain
intervals = [(2, 6), (0, 3), (9, 10)]

ranges = chain.from_iterable(range(i, j+1) for i, j in l)
min(set(range(10)).difference(ranges))
# 7

细节

第一步使用生成器理解并调用
range
,使用每个
元组中的两个元素,从元组中包含的范围创建一个。使用以下方法将结果展平:

现在,我们只需要查找此集合与
范围
n

diff = set(range(10)).difference(ranges)
# {7, 8}
这里有一种方法:

from itertools import chain
intervals = [(2, 6), (0, 3), (9, 10)]

ranges = chain.from_iterable(range(i, j+1) for i, j in l)
min(set(range(10)).difference(ranges))
# 7

细节

第一步使用生成器理解并调用
range
,使用每个
元组中的两个元素,从元组中包含的范围创建一个。使用以下方法将结果展平:

现在,我们只需要查找此集合与
范围
n

diff = set(range(10)).difference(ranges)
# {7, 8}

我这里没有Python要检查,但是您的函数似乎没有返回任何内容,所以
print(最小的\u数(间隔))
prints
None

def smallest_number(intervals):
   i = 0
   while True:
      for first, second in intervals:
      if i in range(first, second + 1):
          i += 1
      else:
          return i

现在
print(最小的\u数(间隔))
应该可以工作了。

我这里没有Python来检查,但是您的函数似乎没有返回任何内容,所以
print(最小的\u数(间隔))
打印
None

def smallest_number(intervals):
   i = 0
   while True:
      for first, second in intervals:
      if i in range(first, second + 1):
          i += 1
      else:
          return i

现在,打印(最小的数字(间隔))
应该可以工作。

在无限循环结束之前,您的代码将打印间隔中的所有数字,而不是那些不在间隔中的数字。试试这个:

def smallest_number(intervals):
    i = 0
    while True:
        for first, second in intervals:
            if i in range(first, second + 1):
                i += 1
                break # break from inner loop
        else:
            break # break from outer loop
    return i # return number

另外,虽然
如果我在范围内(第一,第二+1):
在Python3中很好(而且很快),但我建议使用
如果第一您的代码将在无限循环结束之前打印间隔内的所有数字,而不是那些不在间隔内的数字。试试这个:

def smallest_number(intervals):
    i = 0
    while True:
        for first, second in intervals:
            if i in range(first, second + 1):
                i += 1
                break # break from inner loop
        else:
            break # break from outer loop
    return i # return number

另外,虽然
如果我在范围内(第一,第二+1):
在Python3中还行(而且速度很快),但我还是建议使用
if first我的解决方案,在没有最小数量的情况下提供保护

checking = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
intervals = [(2, 6), (0, 3), (9, 10)]
min_number = None

unique = set()
for left, right in intervals:
    unique.update(range(left, right + 1))

subset = set(checking) - unique
if subset:
    min_number = min(subset)

print(min_number)

我的解决方案在没有最小数量的情况下提供保护

checking = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
intervals = [(2, 6), (0, 3), (9, 10)]
min_number = None

unique = set()
for left, right in intervals:
    unique.update(range(left, right + 1))

subset = set(checking) - unique
if subset:
    min_number = min(subset)

print(min_number)

如果您想要一个允许的数字列表,而不仅仅是最小的,那么这可能是一个不错的选择

import itertools


def flatten(list_of_sublists):
    return itertools.chain.from_iterable(list_of_sublists)


def excluded_numbers(intervals):
    excluded_ranges = [range(lower, upper + 1) for lower, upper in intervals]
    excluded_numbers = set(flatten(excluded_ranges))
    return excluded_numbers


def permitted_numbers(intervals):
    excluded = excluded_numbers(intervals)
    max_excluded = max(excluded)
    candidates = set(range(max_excluded + 2))
    return candidates - excluded


def smallest_number(intervals):
    return min(permitted_numbers(intervals))

如果您想要一个允许的数字列表,而不仅仅是最小的,那么这可能是一个不错的选择

import itertools


def flatten(list_of_sublists):
    return itertools.chain.from_iterable(list_of_sublists)


def excluded_numbers(intervals):
    excluded_ranges = [range(lower, upper + 1) for lower, upper in intervals]
    excluded_numbers = set(flatten(excluded_ranges))
    return excluded_numbers


def permitted_numbers(intervals):
    excluded = excluded_numbers(intervals)
    max_excluded = max(excluded)
    candidates = set(range(max_excluded + 2))
    return candidates - excluded


def smallest_number(intervals):
    return min(permitted_numbers(intervals))

按间隔的起点(如果起点相等,则为终点)对间隔进行排序。然后从第一个间隔开始,继续扩展右边界,直到下一个间隔的起点大于当前覆盖范围的终点

Take (2,6),(0,3),(9,10)
Sorting: (0,3),(2,6),(9,10)
current coverage = [0,3]

因为3<6和2根据它们的起点对间隔进行排序(如果起点相等,则为终点)。然后从第一个间隔开始,继续扩展右边界,直到下一个间隔的起点大于当前覆盖范围的终点

Take (2,6),(0,3),(9,10)
Sorting: (0,3),(2,6),(9,10)
current coverage = [0,3]

既然3<6和2,为什么要“打印”最小的_数?你的函数不返回任何值,所以只要用
最小的\u数(间隔)
调用它就足够了。@Reda Drissi,因为我不想让它返回值,但它不适用于
返回i
。然后你应该使用
返回
语句,在你的if i in范围内,删除
打印(i)
并放置一个
否则:返回i
。为什么要“打印”最小的\u号?你的函数不返回任何值,所以只要用
最小的\u数(间隔)
调用它就足够了。@Reda Drissi,因为我不想让它返回值,但它不适用于
返回i
。然后你应该使用
返回
语句,在你的if i in范围内,删除
打印(i)
并放置一个
否则:返回i
。间隔应该是包含的,因此您需要调整答案,使其采用范围(最小,最大+1)
范围(10)
->
范围(12)
检测最小数字高于最高排除数字的情况间隔应该是包含的,因此,您需要调整您的答案,使其采用范围(最小,最大+1)
range(10)
->
range(12)
检测最小数高于最高排除数的情况,这将返回不在所有间隔内的最小
i
。这将返回不在所有间隔内的最小
i