Merge Multiple Lists of Lists Based on Template

血红的双手。 提交于 2019-12-11 01:14:21

问题


I have 3 DB calls returning a tuple of tuples with a name, code and count like so:

year = (('Fanklin Grand Isle', '5560', 1), ('Windham', '3457', 1))

month = (('Fanklin Grand Isle', '5560', 1), ('Chittendon', '3367', 1))

week = (('Fanklin Grand Isle', '5560', 1), ('Chittendon', '3367', 1))

I need to merge these all together so that they will have the Name, code and count for yearly, monthly and weekly.

My problem is that if there is no record I need to insert the Name and code in AND a 0 value for the counts. The end product should be something like:

result = (('Windham', '0905', 1, 1, 0), ('Windsor Windham', '7852', 0, 0, 0), ('Washington', '3292', 0, 0, 0),
            ('Orleans Essex', '44072', 1, 1, 0), ('Addison', '2853', 0), ('Bennington', '3778', 0),
            ('Fanklin Grand Isle', '5560', 0, 0 0), ('Caledonia', '1992', 0, 0, 0),
            ('Rutland', '2395', 1, 0, 0), ('Chittendon', '3367', 1, 1, 0), ('Lamoille', '5229',0, 0 0))

I was trying to nest a loop to check if the name was present in the DB call and the template. IF if was append the DB value to the list, if not append 0

i = 0
for p in newlist:
    try:
        if p[0] == mlist[i][0]:
            print("HERE: {} {}".format(p[0], mlist[i][0]))
            p.append(mlist[i][-1])
            i += 1
        else:
            p.append(0)
    except IndexError:
        continue

This is appending the DB value but not the zero. I am sure there must be a better way to do this and get it to actually work.

Edit

Here is the updated code based on answers received. For me it is still replacing each year value with a 0.

DATA:

year = (('Fanklin Grand Isle', '5560', 1), ('Windham', '0905', 0), ('Windsor Windham', '7852', 0), ('Washington', '3292', 0), ('Orleans Essex', '44072', 0), ('Chittendon', '18028633367', 1), ('Addison', '12853', 0), ('Bennington', '3778', 0), ('Caledonia', '11992', 0), ('Rutland', '1895', 0), ('Chittendon', '18367', 0), ('Lamoille', '1809', 0), ('Windham', '180905', 0), ('Windsor Windham', '180852', 0), ('Waston', '18022623292', 0), ('Orleans Essex', '18072', 0), ('Addison', '1853', 0), ('Bennington', '1778', 0), ('Fanklin Grand Isle', '18560', 0), ('Caledonia', '180292', 0), ('Rutland', '195', 0), ('Lamoille', '18229', 0))

month = (('Fanklin Grand Isle', '5560', 1), ('Chittendon', '18028633367', 1))

week = (('Fanklin Grand Isle', '5560', 1), ('Chittendon', '18367', 1))

Code:

from collections import defaultdict
joined_data = defaultdict([0, 0, 0].copy)

for entry in year:
    # we create the default entry by calling the defaultdict with a key
    # and immediately grab the newly created list
    count = joined_data[(entry[0],entry[1])]
    # we swap *inplace* the value given by the DB query
    count[0] = entry[2]

# rinse and repeat with the rest of the data
for entry in month:
    count = joined_data[(entry[0], entry[1])]
    count[1] = entry[2]

for entry in week:
    count = joined_data[(entry[0], entry[1])]
    count[2] = entry[2]

# Finally we format the data to the required format
result = tuple(key+tuple(value) for key,value in joined_data.items() )
print(result)

Result:

(('Fanklin Grand Isle', '5560', 0, 1, 1), ('Windham', '0905', 0, 0, 0), ('Windsor Windham', '7852', 0, 0, 0), ('Washington', '3292', 0, 0, 0), ('Orleans Essex', '1072', 0, 0, 0), ('Chittendon', '13367', 0, 1, 1), ('Addison', '2853', 0, 0, 0), ('Bennington', '1878', 0, 0, 0), ('Caledonia', '1992', 0, 0, 0), ('Rutland', '2395', 0, 0, 0), ('Lamoille', '5229', 0, 0, 0))


回答1:


Here's a way to deal with your issue using a defaultdict to avoid having to care about the missing entries :

year = (('Fanklin Grand Isle', '5560', 1), ('Windham', '3457', 1))
month = (('Fanklin Grand Isle', '5560', 1), ('Chittendon', '3367', 1))
week = (('Fanklin Grand Isle', '5560', 1), ('Chittendon', '3367', 1))

#I'm using a defaultdict to deal with the missing entries
from collections import defaultdict
joined_data = defaultdict([0,0,0].copy)

for entry in year:
    #we create the default entry by calling the defaultdict with a key
    #and immediately grab the newly created list
    count = joined_data[(entry[0],entry[1])]
    #we swap *inplace* the value given by the DB query
    count[0] = entry[2]

#rinse and repeat with the rest of the data
for entry in month:
    count = joined_data[(entry[0],entry[1])]
    count[1] = entry[2]

for entry in week:
    count = joined_data[(entry[0],entry[1])]
    count[2] = entry[2]

#Finally we format the data to the required format
result = tuple(key+tuple(value) for key,value in joined_data.items() )
print(result)

Output:

>>>(('Chittendon', '3367', 0, 1, 1), ('Fanklin Grand Isle', '5560', 1, 1, 1), ('Windham', '3457', 1, 0, 0))



回答2:


Not sure I understand what you are trying to achieve, as your example input does not really match your output, but I think you can just use a list comprehension to construct the result, checking whether those items are in the years, months and weeks lists, and adding a 1 or 0 respectively:

>>> year = (('Fanklin Grand Isle', '5560', 1), ('Windham', '3457', 1))
>>> month = (('Fanklin Grand Isle', '5560', 1), ('Chittendon', '3367', 1))
>>> week = (('Fanklin Grand Isle', '5560', 1), ('Chittendon', '3367', 1))
>>> [(x[0], x[1], int(x in year), int(x in month), int(x in week)) for x in set(year + week + month)]
[('Chittendon', '3367', 0, 1, 1),
 ('Windham', '3457', 1, 0, 0),
 ('Fanklin Grand Isle', '5560', 1, 1, 1)]

If those counts can actually be different from 1, you should first create a few dictionaries mapping the cities to their respective year/month/week counts, and then use a similar list comprehension as above:

>>> year_counts = {(name, code): count for (name, code, count) in year}
>>> month_counts = {(name, code): count for (name, code, count) in month}
>>> week_counts = {(name, code): count for (name, code, count) in week}
>>> all_cities = [(name, code) for (name, code, count) in set(year + month + week)]
>>> [(x[0], x[1], year_counts.get(x, 0), month_counts.get(x, 0), week_counts.get(x, 0)) for x in all_cities]
[('Chittendon', '3367', 0, 1, 1),
 ('Windham', '3457', 1, 0, 0),
 ('Fanklin Grand Isle', '5560', 1, 1, 1)]


来源:https://stackoverflow.com/questions/46774105/merge-multiple-lists-of-lists-based-on-template

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!