创建一个包含每个交易文件的列表

时间:2018-12-11 22:02:45

标签: python

晚上好,我想在阅读文本文件(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]] 任何帮助,谢谢你。

4 个答案:

答案 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())

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