0

我有一个如下所示的文本文件:

BALLOTS CAST
Riding 0
YES YES NO YES
NO NO NO NO 
.
.
.
YES NO YES YES

Riding 1
YES NO NO YES
NO NO YES NO 
.
.
.
YES YES YES YES

等等。我有用户输入的骑行号码riding,然后我需要为该骑行制作一个投票列表。例如,如果骑行选择是 0,那么我需要一个 list [[YES YES NO YES], [NO NO NO NO], ..., [YES NO YES YES]]

我需要找出一种使用方法readline()while循环。这大概是我所拥有的:

ballots = open(FILENAME, 'r')
line = ballots.readline().rstrip()
L = []
i = 0
if riding.isdigit():
    while i < ???:
        line = ballots.readline().rstrip()
        i += 1
        if line == 'Riding ' + riding:
            while line != '\n':
                L.append(line.rstrip().split())

但我只是得到一个空列表。我也尝试了这个,180而不是???因为那是有多少行,但我不知道实际放在它的位置上的是什么。我试过max(enumerate(ballots))[0]了,但它ballots完全清空了列表(或者以其他方式使所有内容都为空)。

谁能指出我的错误以及我应该改变什么?正如我所说,我必须使用readline()并且while我不能导入任何东西。

另外,我提出的原因if riding.isdigit()是因为还有选择all骑行的选项。有用:

if riding == 'all':
    line = ballots.readline().rstrip()
    for line in ballots:
        if line[0:6] != 'Riding' and line != '\n':
            L.append(line.rstrip().split())

唯一的问题是我不知道如何使用while循环而不是for循环......

4

3 回答 3

3

看看 Pickle:http ://docs.python.org/2.7/library/pickle.html?highlight=pickle#pickle 它对于保存和恢复 python 对象到文件非常有用,例如列表。

于 2012-11-28T09:28:07.143 回答
2

您需要使用状态变量来检测何时应该读取行,以及何时完成break循环:

lines = []
with open(FILENAME, 'r') as ballots:
    foundriding = False
    ballots.next()  # skip first line
    for line in ballots:
        if line.rstrip() == 'Riding ' + riding:
            foundriding = True
            continue
        if not foundriding: 
            continue
        line = line.rstrip()
        if line and not line.startswith('Riding '):
            lines.append(line)
        else:
            break

上面的代码将跳过所有行,直到找到正确的Riding <number>行,此时它将设置foundriding为 True。设置标志后,它将添加所有后续行,lines直到找到一个空行或另一个以Riding. 那时它将打破阅读循环。

另一种选择是使用itertools.takewhile()

from itertools import takewhile
with open(FILENAME, 'r') as ballots:
    ballots.next()  # skip first line
    for line in takewhile(lambda l: l.rstrip() != 'Riding ' + riding, ballots):
        pass  # skip lines
    lines = [l.rstrip() for l in takewhile(lambda l: l.rstrip() and not l.startswith('Riding '), ballots)]

takewhile将从选票中取行,直到测试返回 False。之后,我们可以通过不同的测试来获取更多行,即该行不为空且不以Riding.

两种解决方案都不需要读取整个文件。当我们找到正确的骑行并且所有投票都已读入时,我们停止阅读lines

ballots像迭代器一样使用文件对象。这与 ; 方法不太一样.readline()。如果.readline()是一个硬性要求(呃,老师和家庭作业),你也可以ballot.readline()变成一个迭代器:

ballotiterator = iter(ballots.readline, '')

然后使用ballotiterator代替ballots你看到的任何地方for line in ballotsballots.next()takewhile(..., ballots)

于 2012-11-28T07:57:52.910 回答
1

使用正则表达式的另一种解决方案:

import re
with open("test.txt") as infile:
    text = infile.read()
    if riding.isdigit():
        section = re.search(r"(?sm)^Riding " + riding + r".*?(?=Riding|\Z)", text)
        matches = re.findall(r"(?:(?:YES|NO) ?)+", section.group(0))
        result = [s.split() for s in matches]
        print(result)

riding设置为,这将"1"导致

[['YES', 'NO', 'NO', 'YES'], ['NO', 'NO', 'YES', 'NO'], ['YES', 'YES', 'YES', 'YES']]

当然,您可能想使用

result = [[True if value == "YES" else False for value in s.split()] 
                                             for s in matches]

相反,为了得到

[[True, False, False, True], [False, False, True, False], [True, True, True, True]]

不进行错误检查(例如Riding x,输入文件中是否存在标记的段),但可以轻松添加。

于 2012-11-28T08:03:20.680 回答