晚上好,我想在阅读文本文件(historique.txt)的同时创建一个列表,该文本文件包含与每个taskid相关的文件列表。考虑以下示例:我的文本文件包含以下行:
4,file1
4,file2
5,file1
5,file3
5,file4
6,file3
6,file4
(用于解释文本文件的更多内容:4是idtask,file1是idtask = 4使用的文件,因此,基本上,使用任务4(file1,file2)。
我想获取交易列表= {[[file1,file2],[file1,file3,file4],[file3,file4]]
任何帮助,谢谢你。
答案 0 :(得分:0)
从文件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']})
答案 1 :(得分:0)
不使用groupby库的替代解决方案
(此解决方案的作用与@mad_完全相同,但是可读性更高,尤其是对于初学者而言):
正如@mad_所说,读取的列表如下:
data=[
'4,file1',
'4,file2',
'5,file1',
'5,file3',
'5,file4',
'6,file3',
'6,file4']
您可以遍历数据,并创建字典
transactions = defaultdict(list)
for element in data: #data[i] is the idtask, data[i+1] is the file
id, file = element.split(',')
transactions[id].append(file)
交易现在将包含字典:
{'4': ['file1', 'file2']
'5': ['file1', 'file3', 'file4']
'6': ['file3', 'file4']}
答案 2 :(得分:0)
如果输入文件未订购
,此操作不不起作用与@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
答案 3 :(得分:0)
我们可以使用csv
模块将行处理为值列表。
csv
从类似文件的对象中读取数据,例如,我们可以使用StringIO
进行伪造:
>>> 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
。
csv.reader
返回一个可迭代的对象。我们可以将整个东西消耗到list
中,只是看它是如何工作的。稍后,我们将改为一次遍历reader
对象一行。
我们可以使用pprint
来查看格式正确的结果:
>>> 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'
我们要构建与密钥具有相同任务的文件名列表。
为了有效地组织这一工作,我们可以使用字典。效率是因为我们可以要求字典查找给定键的值列表。它将密钥存储在某种树中,并且搜索树比线性搜索要快。
我们第一次希望为字典中的特定键添加一个值时,需要检查它是否已经存在。 如果没有,我们将添加一个空列表并将新值附加到该列表中。否则,我们只会将值添加到给定键的现有列表中。
这种模式非常普遍,以至于Python的内置字典具有方法dict.setdefault
来帮助我们实现这一目标。
但是,我不喜欢名称或语法不统一。如果愿意,您可以阅读链接的文档,但我宁愿使用
而是使用Python的defaultdict
。如果您在查询键时还不存在默认值,则会自动为它创建一个默认值。
我们创建一个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())
但是,这可能与原始文件的任务顺序不同。如果这对您很重要,请澄清问题并发表评论,以便我提供帮助。