1

I have a requirement in which I need create dictionary objects with duplicate keys embedded into a list object, something like this:

[{ "key": "ABC" },{ "key": "EFG" } ]

I decided to have a top level list initialized to empty like outer_list=[] and a placeholder dictionary object like dict_obj= {}. Next I keep adding elements to my list using the following steps:

  1. assign { "key": "ABC" } to dict_obj using dict_obj["key"]="ABC"
  2. Add this object to the list using outer_list.append(dict_obj)
  3. Flush/pop the key/items in dictionary object using dict_obj.clear()
  4. Repeat steps 1 to 3 based on the number of key/item combinations in my data

Issue: the outer_list object maintains a reference to the original dict_obj and if the dict_obj is flushed or a new key/item is added it changes accordingly. So finally, I end up with this [{ "key": "EFG" },{ "key": "EFG" } ] instead of [{ "key": "ABC" },{ "key": "EFG" } ]

Please guide me with some workarounds if possible.

Blckknght
  • 100,903
  • 11
  • 120
  • 169

2 Answers2

2

I think there are two ways to avoid the duplicate references.

The first is to append a copy of the dictionary, instead of a reference to it. dict instances have a copy method, so this is easy. Just change your current append call to:

outer_list.append(dict_obj.copy())`

The other option is to not always use the same dict_obj object, but rather create a separate dictionary object for each entry. In this version, you'd replace your call to dict_obj.clear() with:

dict_obj = {}

For the second approach, you might choose to reorder things rather than doing a straight one-line replacement. You could move the setup code to the start of the loop and get rid of the reset logic at the end of the loop.

That is, change code that looks like this:

outer_list = []
dict_obj = {}
for foo in whatever:
    # add stuff to dict_obj
    outer_list.append(dict_obj)
    dict_obj.clear()

To:

outer_list = []
for foo in whatever:
    dict_obj = {}
    # add stuff to dict_obj
    outer_list.append(dict_obj)

If the logic for creating the inner dictionaries is simple enough to compute, you might even turn the whole thing into a list comprehension:

outer_list = [{"key": value, "key2": value2} for value, value2 in some_sequence]
Blckknght
  • 100,903
  • 11
  • 120
  • 169
  • Thanks @Blckknght the first option you pointed out works for me. I need to accumulate the key values in my list till a certain condition is satisfied and then reset it once its done(and go for the next iteration). I had a few issues with the order of flushing the list contents but that mainly had to do with data. I also realized that if my key is same I need not even reset my dictionary object dict_obj as the key value for the same id would get overwritten anyway. – Abhishek Ghosh Sep 15 '16 at 07:22
0

The following should be self-explanatory:

# object reuse
d = {}
l = []
d['key'] = 'ABC'
l.append(d)
d.clear()
print(l) # [{}] : cleared!
d['key'] = 'EFG'
l.append(d)
print(l) # [{'key': 'EFG'}, {'key': 'EFG'}]


# explicit creation of new objects
d = {}
l  = []
d['key'] = 'ABC'
l.append(d)
print(l)
d = {}
d['key'] = 'EFG'
l.append(d)
print(l)
coder.in.me
  • 1,048
  • 9
  • 19