Python 遍历一行数字以找到未使用的数字

Python loop through a row of numbers to find the ones which are not being used

我正在尝试制作一个循环遍历文本文件的 python 脚本。在文本文件中,我有一些类似的东西:

abc1
abc2
abc3
abc5
abc6

现在我希望它遍历所有这些并找到未使用的数字。在这种情况下,它将是 abc4 并打印它。但我卡住了。我试过寻找解决这个问题的方法,但似乎无法解决问题以获得好的答案......

我希望有人能帮助我或指出正确的方向!

我会补充的。文本始终是 abcN(N = 数字)数字也在一行中。就像在例子中

读取数据,丢弃文本,只保留数字。将数字放在 set 中,同时找到最大值。这将确保您拥有文件中的所有数字,没有重复,以及要查找的最大数字。

一旦你有了集合中的数字,只需从零循环到最大值,并检查数字是否是in集合。

这可能不是最有效的或 Pythonic 解决方案,但它是一个解决方案。

试试这个:

import re
my_numbers = [int(re.search('\d+', line).group()) for line in open('myfile.txt')]
reference_numbers = range(0, max(my_numbers))
missing_numbers = [num for num in reference_numbers if num not in my_numbers]

如果可以在不读取文件的情况下生成所有可能的条目(例如,如果 N 被限制在一个固定范围内,比如 0-9),您可以将所有这些构建到一个集合中,使用类似:

possibilities = {'abc{}'.format(i) for i in range(10)}

然后您可以生成一组与文件中实际存在的条目类似的条目:

entries = set(file)

那么你的问题就简化为"the things in the set possibilities which are not also in entries",直接设置支持:

missing = possibilities - entries

如果possibilities的大小很大,您可能希望用数字填充它,并从文件中的每个条目中解析出数字。如果它仅受文件中实际存在的最大数字的限制,则需要从 entries.

动态生成它

如果文件足够大,一次将所有条目和所有可能性都保存在内存中是令人望而却步的,您可以通过使用嵌套循环来利用顺序。创建一个生成器只为您提供数字:

entries = (parse_num(line) for line in file)

(其中 parse_numabcN 并给你 N,作为一个整数)。然后,您可以遍历这些行,同时保留一个单独的计数器,记录您 期望 达到的位置 - 只要它与您 的位置不同到,你有一个缺失值:

expected = 0
for entry in entries:
    while expected < entry:
        yield expected
        expected += 1

对于小文件:

with open("file") as inp:
    c=[]
    for line in inp:
        c.append(int(line.strip("abc")))

check=set(range(min(c),max(c)+1))
print c
print check
print "difference : "+" ".join(map(str,check-set(c)))
[1, 2, 3, 5, 6]
{1, 2, 3, 4, 5, 6}
difference : 4

您可以使用 set 而不是 list

如果您想使用 itertools 来获得不定性,使用生成器的 pythonic 解决方案似乎是理想的。 值得注意的是,它可以很好地处理边缘情况并且具有高度可扩展性。

实施

from itertools import tee, izip, islice
with open("test.txt") as fin:
    fin1, fin2 = tee((int(line[3:]) for line in fin))
    print [line1 + 1 for line2, line1 in izip(islice(fin2 , None), fin1) 
           if line2 - line1 > 1]

输出(相同输入)

abc1
abc2
abc3
abc5
abc6
abc8

[4, 7]

如建议的那样,这是一种可能解决方案的实现:

nums=[]
for line in file:
    i = int(line[3:])
    nums.append(i);

singles=set(nums)
max=max(singles)
missing=[]
for k in range(max):
   if k not in singles:
       missing.appens(k)

print missing

希望对你有所帮助!

由于 OP 指出数字将按顺序排列,我想到了这个解决方案,它总是期望以下行的 nextnum

import re
nextnum = 1
for line in open('input_file.txt'):
    match = re.search(r'abc(\d+)$', line)
    if not match:
        print('error: line "%s" did not match' % line)
        continue
    linenum = int(match.group(1))
    if linenum > nextnum:
        print('line abc%d skipped, found abc%d!' % (nextnum, linenum))
    nextnum = linenum + 1

请注意,即使缺少多个后续数字,这也只会给出一个 "skipped" 输出,因为它只会期望下一行的当前行数字加一。