我正在解析两个大文件(Gb大小顺序),每个文件包含keys
和相应的values
。一些keys
在两个文件之间共享,但具有不同的对应values
。
对于每个文件,我想写一个新文件keys*
和相应的values
,其中keys*
表示在file1和file2中都存在的键。我不关心输出中的key
顺序,但两个文件中的顺序应完全相同。
文件1:
key1
value1-1
key2
value1-2
key3
value1-3
文件2:
key1
value2-1
key5
value2-5
key2
value2-2
有效输出为:
解析文件1:
key1
value1-1
key2
value1-2
解析文件2:
key1
value2-1
key2
value2-2
其他有效输出:
解析文件1:
key2
value1-2
key1
value1-1
解析文件2:
key2
value2-2
key1
value2-1
无效输出(文件1和文件2中按键顺序不同):
解析文件1:
key2
value1-2
key1
value1-1
解析文件2:
key1
value2-1
key2
value2-2
最后一个精度是,值大小远远大于键大小。
我想要做的是:
对于每个输入文件,使用与文件中的键对应的键解析并返回dict
(让我们称之为file_index
),以及与键所在的偏移量对应的值在输入文件中找到。
计算交叉点
good_keys = file1_index.viewkeys() & file2_index.viewkeys()
执行类似(伪代码)的操作:
for each file:
for good_key in good_keys:
offset = file_index[good_key]
go to offset in input_file
get corresponding value
write (key, value) to output file
迭代相同的集合是否保证我具有完全相同的顺序(假设它是相同的集合:我不会在两次迭代之间修改它),或者我应该转换先设置一个列表,然后遍历列表?
答案 0 :(得分:6)
Python的dicts和set是稳定的,也就是说,如果你在不改变它们的情况下迭代它们,它们可以保证给你相同的顺序。这来自documentation on dicts:
键和值以任意顺序迭代,这是非随机的,在Python实现中各不相同,并且取决于字典的插入和删除历史。如果迭代了键,值和项视图而没有对字典进行干预修改,则项的顺序将直接对应。
答案 1 :(得分:3)
对未经修改的集合进行迭代将始终为您提供相同的顺序。订单由当前值及其插入历史记录提供。
如果您对为什么感兴趣,请参阅Why is the order in dictionaries and sets arbitrary?。
请注意,如果您想要修改文件 ,那么只有当您的条目具有固定大小时才能使用。无法在中间某处更新文件,其中更新包含的字符数少于您替换的字符数。
文件中的数据就像磁带一样,您必须拼接更长或更短的部分来替换中间的数据,但是您无法使用文件进行拼接。您必须重写替换后的键值对之后的所有内容才能使其余部分适合。
答案 2 :(得分:0)
如前所述,只要你不改变它,dicts和sets就是稳定的并提供相同的顺序。如果您需要特定订单,可以使用OrderedDict
来自馆藏文档:
>>> from collections import OrderedDict
>>> # regular unsorted dictionary
>>> d = {'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}
>>> # dictionary sorted by key -- OrderedDict(sorted(d.items()) also works
>>> OrderedDict(sorted(d.items(), key=lambda t: t[0]))
OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])
>>> # dictionary sorted by value
>>> OrderedDict(sorted(d.items(), key=lambda t: t[1]))
OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])
>>> # dictionary sorted by length of the key string
>>> OrderedDict(sorted(d.items(), key=lambda t: len(t[0])))
OrderedDict([('pear', 1), ('apple', 4), ('orange', 2), ('banana', 3)])