Python 集合的迭代顺序

Python iteration order on a set

我正在解析两个大文件(Gb 大小顺序),每个文件都包含 keys 和相应的 values。一些 keys 在两个文件之间共享,但对应的 values 不同。 对于每个文件,我想将 keys* 和相应的 values 写入一个新文件,其中 keys* 表示文件 1 和文件 2 中都存在的键。我不关心输出中的 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

最后一个精度是值的大小远远大于键的大小。

我想做的是:

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

对未修改的集合进行迭代将始终为您提供相同的顺序。该顺序由当前值及其插入历史记录决定。

如果您对为什么感兴趣,请参阅Why is the order in dictionaries and sets arbitrary?

请注意,如果您想就地修改您的文件,那么只有当您的条目具有固定大小时才有效。文件无法在中间某处更新,更新包含的字符少于或多于您替换的字符。

文件中的数据就像磁带,您必须拼接更长或更短的部分以替换中间的数据,但文件不能这样做。您必须重写替换后的键值对之后的所有内容才能使其余部分适合。

Python 的字典和集合是稳定的,也就是说,如果你在不改变它们的情况下迭代它们,它们保证给你相同的顺序。这是来自 documentation on dicts:

Keys and values are iterated over in an arbitrary order which is non-random, varies across Python implementations, and depends on the dictionary’s history of insertions and deletions. If keys, values and items views are iterated over with no intervening modifications to the dictionary, the order of items will directly correspond.

如前所述,dicts 和 sets 是稳定的,只要您不更改它,就会提供相同的顺序。如果你想要一个特定的订单,你可以使用 OrderedDict

来自 collections 库文档:

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