'Dictionary appends to same parent

I am trying to append to the parent but Python doesn't append to the parent.

data = [(33, 'paypal.com', 'Alexa Pages'), (33, 'paypal.com', '404 Pages'), (32, 'stackoverflow.com', 'Alexa Pages'), (2, 'reddit.com', None), (1, 'yahoo.com', 'Alexa Pages'), (1, 'yahoo.com', '404 Pages')]

res = defaultdict(list)
for id, subdomain, name in data:
    res[id].append(name)
    #res[id].append(subdomain)

resjson=[]
for id, name in res.items():
    resjson.append({'id':id, 'name':name, 'subdomain':subdomain} )

Returns

[
  {
    "id": 33,
    "name": [
      "Alexa Pages",
      "404 Pages"
    ],
    "subdomain": "paypal.com"
  },
  {
    "id": 32,
    "name": [
      "Alexa Pages"
    ],
    "subdomain": "paypal.com"
  },
  {
    "id": 2,
    "name": [
      null
    ],
    "subdomain": "paypal.com"
  },
  {
    "id": 1,
    "name": [
      "Alexa Pages",
      "404 Pages"
    ],
    "subdomain": "paypal.com"
  }
]

When I try to append "subdomain" to the dictionary, it appends to the name field.

data = [(33, 'paypal.com', 'Alexa Pages'), (33, 'paypal.com', '404 Pages'), (32, 'stackoverflow.com', 'Alexa Pages'), (2, 'reddit.com', None), (1, 'yahoo.com', 'Alexa Pages'), (1, 'yahoo.com', '404 Pages')]

res = defaultdict(list)
for id, subdomain, name in data:
    res[id].append(name)
    res[id].append(subdomain)

resjson=[]
for id, name in res.items():
    resjson.append({'id':id, 'name':name, 'subdomain':subdomain} )

Returns


[
  {
    "id": 33,
    "name": [
      "Alexa Pages",
      "paypal.com",
      "404 Pages",
      "paypal.com",
    ],
    "subdomain": "paypal.com"
  },
  {
    "id": 32,
    "name": [
      "Alexa Pages",
      "stackoverflow.com"
    ],
    "subdomain": "paypal.com"
  },
  {
    "id": 2,
    "name": [
      null,
      "reddit.com"
    ],
    "subdomain": "paypal.com"
  },
  {
    "id": 1,
    "name": [
      "Alexa Pages",
      "yahoo.com",
      "404 Pages",
      "yahoo.com"
    ],
    "subdomain": "paypal.com"
  }
]

There is the main problem:

  • It doesn't update the "subdomain" field.
  • When I try to add subdomain in this loop: for id, name, subdomain in res.items(), I get the ValueError: not enough values to unpack (expected 3, got 2) error.


Solution 1:[1]

There are two main problems:

  • You are appending two values to the id key i.e name and subdomain in each iteration. When you are iterating over the values the second time to create a list of dictionary values, the name property has all the id and subdomain values in it.
  • Subdomain property value in the second for loop is taken from the previous for loop last iteration i.e "yahoo.com" thus all the entries have the same subdomain value in the result list

Solution.

data = [(33, 'paypal.com', 'Alexa Pages'), (33, 'paypal.com', '404 Pages'), (32, 'stackoverflow.com', 'Alexa Pages'), (2, 'reddit.com', None), (1, 'yahoo.com', 'Alexa Pages'), (1, 'yahoo.com', '404 Pages')]
res = dict()

for websiteId, subdomain, name in data:
    if websiteId in res:
        res[websiteId]["name"].append(name)
    else:
        res[websiteId] = {
            "id": websiteId,
            "name": [name],
            "subdomain": subdomain
        }

res = [res[key] for key in res.keys()]
print(res)

Solution 2:[2]

If you're attempting to combine the name elements for the same id and subdomain then you can loop through your data and add them to a dictionary.

Whilst iterating, perform a check to see if the ID already exists in the dictionary, and if it does then append the name, otherwise add it as a list.

from pprint import pprint

data = [
    (33, 'paypal.com', 'Alexa Pages'), 
    (33, 'paypal.com', '404 Pages'), 
    (32, 'stackoverflow.com', 'Alexa Pages'), 
    (2, 'reddit.com', None), 
    (1, 'yahoo.com', 'Alexa Pages'), 
    (1, 'yahoo.com', '404 Pages')
]

resjson={}
for id, subdomain, name in data:
    if id in resjson:
        names = resjson[id]['name']
        names.append(name)
        resjson[id]['name'] = names
    else:
        resjson[id] = {'subdomain': subdomain, 'name': [name]}

pprint(resjson)

Outputs

{1: {'name': ['Alexa Pages', '404 Pages'], 'subdomain': 'yahoo.com'},
2: {'name': [None], 'subdomain': 'reddit.com'},
32: {'name': ['Alexa Pages'], 'subdomain': 'stackoverflow.com'},
33: {'name': ['Alexa Pages', '404 Pages'], 'subdomain': 'paypal.com'}}  

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 kkk
Solution 2 AdamMcKay