Python自生变量?

2024-09-27 00:21:15 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在写一个程序,读取一个大的.txt文件与乐透号码。这意味着一个数组中总是有7个int。(49中的6,最后一个是超数)。你知道吗

例如:[[1,11,25,37,39,47,0],[3,13,15,18,37,46,0],…]

我每个月都有这个.txt,意思是

January:
[1, 11, 25, 37, 39, 47, 0]
[3, 13, 15, 18, 37, 46, 2]
[3,  6,  9, 12, 37, 46, 6]

February:
[3, 13, 15, 18, 37, 46, 0]
[1, 23, 17, 18, 37, 46, 8]

...

等等

如何生成一个只读取月份数的数组?你知道吗

我有一个解决方案,但它是非常糟糕的编码风格:

jan_tipps = []
feb_tipps = []
mar_tipps = []

#variable wich month has to be checked
jan = False
feb = False
mar = False

for line in wholefile:
    if line == '\n':
        pass
    elif line == 'January:\n':
        jan = True
    elif line == 'February:\n':
        jan = False
        feb = True
    elif line == 'March:\n':
        feb = False
        mar = True
    elif jan == True:
        jan_tipps.append(line.split())

    elif feb == True:
        feb_tipps.append(line.split())

    elif mar == True:
        mar_tipps.append(line.split())

我想我需要像泛型或者自生变量之类的东西。我不知道我要在网上搜索什么。你知道吗


Tags: 程序txtfalsetrueline数组marjan
3条回答

可以使用正则表达式:

import re

lotto = """
January:
[1, 11, 25, 37, 39, 47, 0]
[3, 13, 15, 18, 37, 46, 2]
[3,  6,  9, 12, 37, 46, 6]

February:
[3, 13, 15, 18, 37, 46, 0]
[1, 23, 17, 18, 37, 46, 8]
"""

def getMonthlyNumbers(month=None):
    rx = re.compile(r'''
        ^{}:[\n\r]
        (?P<numbers>(?:^\[.+\][\n\r]?)+)'''.format(month), re.M | re.X)

    for match in rx.finditer(lotto):
        # print it or do sth. else here
        print(match.group('numbers'))

getMonthlyNumbers('January')
getMonthlyNumbers('February')


或者,对于所有月份,使用听写理解:
rx = re.compile(r'^(?P<month>\w+):[\n\r](?P<numbers>(?:^\[.+\][\n\r]?)+)', re.MULTILINE)

result = {m.group('month'): m.group('numbers') for m in rx.finditer(lotto)}

print(result)

这就产生了

{'January': '[1, 11, 25, 37, 39, 47, 0]\n[3, 13, 15, 18, 37, 46, 2]\n[3,  6,  9, 12, 37, 46, 6]\n', 'February': '[3, 13, 15, 18, 37, 46, 0]\n[1, 23, 17, 18, 37, 46, 8]\n'}

这里的想法是在行首查找月份名称,然后捕获任何[...]对。见a demo on regex101.com


可能,您希望将每一行单独作为一个列表(而不是字符串),因此您可以选择:
import re
from ast import literal_eval

lotto = """
January:
[1, 11, 25, 37, 39, 47, 0]
[3, 13, 15, 18, 37, 46, 2]
[3,  6,  9, 12, 37, 46, 6]

February:
[3, 13, 15, 18, 37, 46, 0]
[1, 23, 17, 18, 37, 46, 8]
"""

rx = re.compile(r'^(?P<month>\w+):[\n\r](?P<numbers>(?:^\[.+\][\n\r]?)+)', re.MULTILINE)

result = {m.group('month'): 
    [literal_eval(numbers) 
    for numbers in m.group('numbers').split("\n") if numbers] 
    for m in rx.finditer(lotto)}

print(result)

正如克劳斯D.评论的那样,你需要一本字典。但我怀疑这还不够暗示。这里有一个更广泛的答案。你知道吗

一个问题:您的代码与您提供的输入数据不一致。代码将数字拆分为空格,但输入数据使用方括号和逗号。此代码与您提供的输入一起工作。你知道吗

# Parser states:
# 0: waiting for a month name
# 1: expecting numbers in the format [1, 11, 25, 37, 39, 47, 0]

from collections import defaultdict

state = 0
tipps = defaultdict(list)
monthname = None

with open("numbers.txt","r") as f:
    for line in f:
        if state == 0:
            if line.strip().endswith(":"):
                monthname = line.split(":")[0]
                state = 1
            continue
        if state == 1:
            if line.startswith("["):
                line = line.strip().strip("[]")
                numbers = line.split(",")
                tipps[monthname].append([int(n) for n in numbers])
            elif not line.strip():
                state = 0
            else:
                print (f"Unexpected data, parser stuck: {line}")
                break

for k,v in tipps.items():
    print (f"{k}: {v}")

输出为:

January: [[1, 11, 25, 37, 39, 47, 0], [3, 13, 15, 18, 37, 46, 2], [3, 6, 9, 12, 37, 46, 6]]
February: [[3, 13, 15, 18, 37, 46, 0], [1, 23, 17, 18, 37, 46, 8]]

创建月份字典,以月份名称作为键,以所需数组的数组作为值

month = {
    m: [] 
    for m in ['January', 'February']
}
with open('file.txt') as file:
    latest = None
    for line in file:
        line = line.strip()
        if line == '':  # striped empty line
            continue
        if line in month:
            latest = line
        else:
            month[latest].append(line.split())  # actually if line="[1, 2]" then better to use eval instaed of split(', ')

相关问题 更多 >

    热门问题