Reputation: 303
I have a text file with contents such as:
{'InventoryTake':'Key','OtherSceneNode':'Shed','AddOtherScene':'ShedOpen'}
And the code that retrieves the data from the text file:
readin = eventVar.readline()
Results = eval(readin)
The problem I'm having is that I need to keep my dictionary in order due to the nature of the code it runs. However python stores dictionary keys in random order.
I have tried using an ordered Dictionary to preserve the order, but this doesn't make a difference. I think this is because by the time the ordered dictionary gets a hold of the information, it has already been sorted by whatever is reading it in from the file.
I have tried eval, literal_eval and a json parser to read the data in correctly, but the dictionary always comes out in the wrong order when running the program.
The aim of this part of the program is to allow the text file dictionary to store as many of those pairs as possible (OtherSceneNode and AddOtherScene / TakeOtherScene). So I can't assume there is only one set of those key value pairs.
I'm using python 2.7.5, and if it helps the order its coming out in is:
{'InventoryTake':'Key','AddOtherScene':'ShedOpen','OtherSceneNode':'Shed'}
I could redo the text files to take specific lines, but that will make my text files even more complicated and I feel its just avoiding a problem rather than solving one.
Upvotes: 0
Views: 1940
Reputation: 7821
This should do the trick, and is shorter than most of the other solutions.
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)
Upvotes: 1
Reputation: 15488
One method would be to look up the parsed data pairs in the string to find their original relative order:
line = "{'InventoryTake':'Key','OtherSceneNode':'Shed','AddOtherScene':'ShedOpen'}"
data = eval(line)
sorted(data.items(), key=lambda pair: line.index("'%s','%s'" % pair)
which gives me:
[('InventoryTake', 'Key'),
('OtherSceneNode', 'Shed'),
('AddOtherScene', 'ShedOpen')]
Upvotes: 1
Reputation: 7187
This got a bit wordy, but it appears to do what you're asking for:
#!/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)
Upvotes: 0