创建一个包含每个事务文件的列表

2024-04-27 02:43:33 发布

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

晚上好,我想在阅读文本文件时创建一个列表(历史.txt)其中包含与每个taskid关联的文件列表。考虑以下示例:我的文本文件包含以下行:

4,file1
4,file2
5,file1
5,file3
5,file4
6,file3
6,file4

(为了更详细地解释文本文件的内容:4是idtask,file1是idtask=4使用的文件,所以基本上,task4使用(file1,file2)。 我想获得list Transactions=[[file1,file2],[file1,file3,file4],[file3,file4]] 任何帮助,谢谢。你知道吗


Tags: 文件txt示例内容列表历史file1list
3条回答

我们可以使用^{}模块将行处理为值列表。你知道吗

csv读取类似文件的对象,我们可以使用^{}对其进行伪造,例如:

>>> from io import StringIO
>>> contents = StringIO('''4,file1
... 4,file2
... 5,file1
... 5,file3
... 5,file4
... 6,file3
... 6,file4''')

注意:根据您使用的Python版本的不同,您可能需要以不同的方式导入StringIO。上面的代码适用于python3。对于Python 2,将导入替换为from StringIO import StringIO。你知道吗

^{}返回一个iterable对象。我们可以把所有的东西都放进一个list,看看它是如何工作的。稍后我们将一次迭代一行reader对象。你知道吗

我们可以使用^{}查看格式良好的结果:

>>> import csv
>>> lines = list(csv.reader(contents))

>>> from pprint import pprint
>>> pprint(lines)
[['4', 'file1'],
 ['4', 'file2'],
 ['5', 'file1'],
 ['5', 'file3'],
 ['5', 'file4'],
 ['6', 'file3'],
 ['6', 'file4']]

然后可以将这些列表解压为任务和文件名:

>>> task, filename = ['4', 'file1']
>>> task
'4'
>>> filename
'file1'

我们希望构建与key具有相同任务的文件名列表。你知道吗

为了有效地组织这件事,我们可以使用字典。效率是因为我们可以要求字典为给定的键找到一个值列表。它将密钥存储在某种树中,搜索树比线性搜索更快。你知道吗

当我们第一次为一个特定的键向字典中添加一个值时,我们需要检查它是否已经存在。 如果不是,我们将添加一个空列表并将新值附加到它。否则,我们只需将该值添加到给定键的现有列表中。你知道吗

这种模式非常常见,Python的内置字典有一个方法^{}来帮助我们实现这一点。 但是,我不喜欢这个名字,或者不统一的语法。如果你愿意,你可以阅读链接的文档,但我宁愿使用 而Python的^{}。如果在查询键时该键不存在,则会自动为该键创建默认值。你知道吗

我们创建一个defaultdict,默认值为list

>>> from collections import defaultdict
>>> d = defaultdict(list)

然后,对于任何新密钥,它将为我们创建一个空的list

>>> d['5']
[]

我们可以附加到list

>>> d['5'].append('file1')
>>> d['7'].append('file2')
>>> d['7'].append('file3')

我将把defaultdict转换成dict,只是为了使它pprint更漂亮:

>>> pprint(dict(d), width=30)
{'5': ['file1'],
 '7': ['file2', 'file3']}

所以,把这些放在一起:

import csv
from collections import defaultdict

from io import StringIO
from pprint import pprint

contents = StringIO('''4,file1
4,file2
5,file1
5,file3
5,file4
6,file3
6,file4''')

task_transactions = defaultdict(list)

for row in csv.reader(contents):
    task, filename = row
    task_transactions[task].append(filename)

pprint(dict(task_transactions))

输出:

{'4': ['file1', 'file2'],
 '5': ['file1', 'file3', 'file4'],
 '6': ['file3', 'file4']}

最后一点注意:在这个示例中,我们使用StringIO来伪造文件内容。您可能希望在实际代码中用以下内容替换它:

with open('historique.txt') as contents:
    for row in csv.reader(contents):
        ...  # etc

此外,我们从csv读取器中取出每一行,然后将其解压为一个任务和文件名,我们可以一次性完成这一切:

for task, filename in csv.reader(contents):

因此,您的整个代码(不打印)将非常简单:

import csv
from collections import defaultdict

task_transactions = defaultdict(list)

with open('historique.txt') as contents:
    for task, filename in csv.reader(contents):
        task_transactions[task].append(filename)

如果您想要事务列表(如您在问题中所问!)地址:

transactions = list(task_transactions.values())

但是,这可能与原始文件的任务顺序不同。如果这对你很重要,请澄清问题并发表评论,以便我能提供帮助。你知道吗

如果输入文件没有排序,这将不起作用

与@mad的答案完全相同,只是展示了将file_data_list变成列表列表而不是字符串列表的好处。我们只需要每行.split一次,这样可读性更强,速度也可能更快。你知道吗

注意这也可以在读取文件时执行,而不是像下面所示的那样在事后执行。你知道吗

from itertools import groupby

file_data_list = ['4,file1',
                  '4,file2',
                  '5,file1',
                  '5,file3',
                  '5,file4',
                  '6,file3',
                  '6,file4']

file_data_list = [line.split(',') for line in file_data_list]

for k, v in groupby(file_data_list, key=lambda x: x[0]):
    print([x[1] for x in v])  # also no need to convert v to list

从文件中读取后,例如f.readlines(),它将给出一个类似于下面的列表

file_data_list=['4,file1',
'4,file2',
'5,file1',
'5,file3',
'5,file4',
'6,file3',
'6,file4']

应用groupby

from itertools import groupby
for k,v in groupby(file_data_list,key=lambda x:x.split(",")[0]):
    print([i.split(",")[1] for i in list(v)])

输出

['file1', 'file2']
['file1', 'file3', 'file4']
['file3', 'file4']

您还可以创建映射dict

for k,v in groupby(file_data_list,key=lambda x:x.split(",")[0]):
    print({k:[i.split(",")[1] for i in list(v)]})

输出

{'4': ['file1', 'file2']}
{'5': ['file1', 'file3', 'file4']}
{'6': ['file3', 'file4']}

正如@DeepSpace所指出的,上述解决方案只有在对id进行排序时才能起作用。未订购时修改

from collections import defaultdict
d=defaultdict(list)
file_data_list=['4,file1',
'4,file2',
'5,file1',
'5,file3',
'5,file4',
'6,file3',
'6,file4',
'4,file3']
for k,v in groupby(file_data_list,key=lambda x:x.split(",")[0]):
    for i in list(v):
        d[k].append(i.split(",")[1])

print(d)

输出

defaultdict(list,
            {'4': ['file1', 'file2', 'file3'],
             '5': ['file1', 'file3', 'file4'],
             '6': ['file3', 'file4']})

相关问题 更多 >