3

I'm trying to write some python functions to generate a batch of input files, in which there is, for instance, this block:

***behavior
**energy_phase_1
ef_v 10
**energy_phase_2
ef_v 7.

So far i was using collections.OrderedDict, because order matters in this kind of input file). For instance,if there are two simulations in my batch:

inp_dict['***behavior'] = [ '', '']
inp_dict['**energy_phase_1'] = [ '', '']
inp_dict['**ef_v'] = [ '10', '20']
inp_dict['**energy_phase_2'] = [ '', '']
inp_dict['**ef_v'] = [ '7', '14']

And to write the file I would just do something like:

for s , n in enumerate(sim_list):
    ......some code...
    inp_file.write(' '.join([ key, val[s], '\n' for key, val in inp_dict.items]))

But as you can see, this is not enough, since it there are duplicates key in the dict.

So my question is: is there an ordered dict that allows for duplicate keys? For instance, if there exists dict['key']=1 and dict['key']=2, first call would return 1 and second 2?

Or, is there some clever and simple way to achieve want I want?

Thanks

Russia Must Remove Putin
  • 374,368
  • 89
  • 403
  • 331
Napseis
  • 833
  • 2
  • 10
  • 24
  • 1
    Why don't you keep dict['key'] as an array, for example [1,2]? Then you can have multiple values for one key rather than multiple keys with different values. – Radoslav Georgiev Feb 22 '14 at 21:55
  • Because dict['key'] is already an array, since I have inp_dict['**ef_v'] = [ value for sim 1 = '10', value for sim2= '20'], as well as inp_dict['**ef_v'] = [ value for sim 1 = '7', value for sim2= '14'], whihc are aprt of different *** blocks. – Napseis Feb 22 '14 at 22:19
  • If one would really want, one could implement a dict-like object that works as described. You'd probably subclass the ABC `collections.Mapping` or `collections.MutableMapping`, internally store the multi-values as a dict of lists and maintain indices to the last returned element of each list. However, returning different things on key lookup feels quite ill-defined and certainly breaks with standard expectations of users. I strongly recommend to rethink the idea. Are these keys really the same if you have different values? Could you make a simple dict of lists and iterate the returned list? – Tim Hoffmann Jun 02 '16 at 02:48

1 Answers1

3

The concept of duplicate key goes against the concept of dict.

If you need to maintain order and have duplicate keys I'd say you need to use another data structure. One possible solution would be using a list of tuples. Something like the following:

inp = list()

# Define your input as a list of tuples instead of as a dict

inp.append(('***behavior', ('', '')))
inp.append(('**energy_phase_1', ('', '')))
inp.append(('**ef_v', ('10', '20')))
inp.append(('**energy_phase_2', ('', '')))
inp.append(('**ef_v', ('7', '14')))

# You can have duplicate keys on the list and the order is preserved

output = "\n".join(["{key} {val}".format(key=t[0], val=t[1][0]).strip() for t in inp])

In this case the output variable would contain:

***behavior
**energy_phase_1
**ef_v 10
**energy_phase_2
**ef_v 7

If you need to access values by key (a dict-like functionality) you could use something like this:

def get_key_values(inp, key):

    filtr_by_key = filter(lambda t: True if t[0] == key else False, inp)
    return filtr_by_key

ef_v_values = get_key_values(inp, "**ef_v")

In this case the ef_v_values would contain only the values associated with the key **ef_v:

[('**ef_v', ('10', '20')), ('**ef_v', ('7', '14'))]

Hope this helps.

agmangas
  • 639
  • 5
  • 9
  • thanks for the answer. I know this goes against the dict philosophy, but it feels like something is lacking between the dict and the tuple objects. I don't quite get the second example at the moment, but maybe the night will make it clearer. – Napseis Feb 22 '14 at 22:27
  • The second example is just a helper function in case you needed to access simulation results contained in *inp* by key (something that in a dict would be straightforward: inp[key]). The real "answer" to your question is only the first part :) – agmangas Feb 22 '14 at 22:32