【问题标题】:Python: Text file to dictionary whilst preserving order?Python:文本文件到字典,同时保留顺序?
【发布时间】:2014-01-05 12:37:35
【问题描述】:

我有一个文本文件,其内容如下:

{'InventoryTake':'Key','OtherSceneNode':'Shed','AddOtherScene':'ShedOpen'}

以及从文本文件中检索数据的代码:

    readin = eventVar.readline()
    Results = eval(readin)

我遇到的问题是,由于它运行的代码的性质,我需要保持我的字典井然有序。然而python以随机顺序存储字典键。

我尝试使用有序字典来保留顺序,但这并没有什么不同。我认为这是因为在有序字典获取信息时,它已经按照从文件中读取的内容进行了排序。

我尝试过 eval、literal_eval 和 json 解析器来正确读取数据,但在运行程序时字典总是以错误的顺序出现。

这部分程序的目的是允许文本文件字典存储尽可能多的这些对(OtherSceneNode 和 AddOtherScene / TakeOtherScene)。所以我不能假设只有一组键值对。

我使用的是 python 2.7.5,如果它有助于命令它的输出是:

{'InventoryTake':'Key','AddOtherScene':'ShedOpen','OtherSceneNode':'Shed'}

我可以重做文本文件以获取特定的行,但这会使我的文本文件更加复杂,我觉得这只是避免问题而不是解决问题。

【问题讨论】:

  • 为什么顺序对您来说很重要?如果顺序真的很重要,您可以将字典转换为列表并将列表写入文件。
  • python 中的字典没有顺序。使用 OrderedDict 保留插入顺序。
  • 为什么要将它们放在字典中(除了能够使用 eval 轻松解析)?如果你想支持重复键,那不是一个合适的容器。
  • 这是一个文字冒险游戏基地。这是来自处理事件的事件文本文件。字典是事件所做更改的列表,例如更新库存。之所以需要按顺序排列,是因为我想控制更改发生的顺序。

标签: python file dictionary eval


【解决方案1】:

这应该可以解决问题,并且比大多数其他解决方案要短。

from collections import OrderedDict

data = []
for line in eventVar.readline():
    # Remove braces
    line = line.strip()[1:-1]
    results = OrderedDict()
    # Split by comma sign
    for pair in line.split(','):
        # Get key and value by splitting on colon
        key, value = pair.split(':')
        # Use eval to get rid of quotation surrounding the key and value
        results[eval(key)] = eval(value)
        # Add the results from reading this line to a list
        data.append(results)

【讨论】:

  • 这对包含逗号的字符串没有问题吗?
  • @dstromberg 有,但从样本输入来看,我认为在这种情况下这不是问题。
【解决方案2】:

一种方法是在字符串中查找已解析的数据对以找到它们的原始相对顺序:

line = "{'InventoryTake':'Key','OtherSceneNode':'Shed','AddOtherScene':'ShedOpen'}"
data = eval(line)
sorted(data.items(), key=lambda pair: line.index("'%s','%s'" % pair)

这给了我:

[('InventoryTake', 'Key'),
('OtherSceneNode', 'Shed'),
('AddOtherScene', 'ShedOpen')]

【讨论】:

    【解决方案3】:

    这有点罗嗦,但它似乎可以满足您的要求:

    #!/usr/local/cpython-3.3/bin/python
    
    import shlex
    import collections
    
    def strip_single_quote(string):
        assert string[0] == "'"
        assert string[-1] == "'"
        return string[1:-1]
    
    def dict_to_tuples(string):
        list_ = list(shlex.shlex(string))
        assert list_[0] == '{'
        assert list_[-1] == '}'
        list_ = list_[1:-1]
        print(list_)
        len_list = len(list_)
    
        for base_index in range(0, len_list, 4):
            assert list_[base_index + 1] == ':'
            if list_[base_index + 3:]:
                assert list_[base_index + 3] == ','
            key = strip_single_quote(list_[base_index + 0])
            value = strip_single_quote(list_[base_index + 2])
            yield (key, value)
    
    def main():
        string = "{'InventoryTake':'Key','OtherSceneNode':'Shed','AddOtherScene':'ShedOpen'}"
        od = collections.OrderedDict(dict_to_tuples(string))
        print(od)
    

    【讨论】:

      猜你喜欢
      • 2015-10-14
      • 1970-01-01
      • 1970-01-01
      • 2012-05-05
      • 1970-01-01
      • 1970-01-01
      • 2018-01-11
      • 1970-01-01
      • 2023-04-05
      相关资源
      最近更新 更多