一组上的Python迭代顺序

时间:2015-02-26 09:31:46

标签: python python-2.7 set iteration

我正在解析两个大文件(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
    

迭代相同的集合是否保证我具有完全相同的顺序(假设它相同的集合:我不会在两次迭代之间修改它),或者我应该转换先设置一个列表,然后遍历列表?

3 个答案:

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