【问题标题】:Python iteration order on a set集合上的 Python 迭代顺序
【发布时间】:2015-04-28 14:38:20
【问题描述】:

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

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

【问题讨论】:

  • 您实际上是在使用字典还是集合?一旦你不改变集合,顺序就不会改变
  • 对于一个简单的问题,有很多文字!将问题放在开头,并删除其他不能改善问题的内容。

标签: python python-2.7 set iteration


【解决方案1】:

Python 的 dicts 和 sets 是稳定的,也就是说,如果您在不更改它们的情况下迭代它们,它们保证给您相同的顺序。这是来自documentation on dicts

键和值以非随机的任意顺序迭代,随 Python 实现而变化,并且取决于字典的插入和删除历史。如果键、值和项目视图被迭代而没有对字典进行干预修改,项目的顺序将直接对应。

【讨论】:

  • 正是我想要的(但在设置文档中没有找到)!谢谢!
  • Pedantry:您引用的文档段落仅保证 dicts 的这一点。是否有任何地方明确为集合提供了相同的保证?
【解决方案2】:

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

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

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

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

【讨论】:

  • 感谢您提供确定性的精确性!
【解决方案3】:

如前所述,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)])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-02
    • 1970-01-01
    • 1970-01-01
    • 2013-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-20
    相关资源
    最近更新 更多