简体   繁体   中英

How to Create a Dictionary Using Keys and Values from a Previous Dictionary?

I need to create a dictionary whose keys are values from a previously created dictionary. My previous dictionary is:

{100000: (400, 'Does not want to build a %SnowMan %StopAsking', ['SnowMan', 'StopAsking'], [100, 200, 300], [400, 500]), 
100001: (200, 'Make the ocean great again.', [''], [], [400]), 
100002: (500, "Help I'm being held captive by a beast!  %OhNoes", ['OhNoes'], [400], [100, 200, 300]), 
100003: (500, "Actually nm. This isn't so bad lolz :P %StockholmeSyndrome", ['StockholmeSyndrome'], [400, 100], []), 
100004: (300, 'If some random dude offers to %ShowYouTheWorld do yourself a favour and %JustSayNo.', ['ShowYouTheWorld', 'JustSayNo'], [500, 200], [400]), 
100005: (400, 'LOLZ BELLE.  %StockholmeSyndrome  %SnowMan', ['StockholmeSyndrome', 'SnowMan'], [], [200, 300, 100, 500])}

This dictionary is of the form {key: (id, string, tags, likes, dislikes)} What I need to create is a dictionary whose keys are the tags from the first dictionary, and whose values are the id and strings which contain the tags, presented in the form of a dictionary.

For example, if we take the tag 'SnowMan' , the new dictionary should look like this:

{'SnowMan': {400: ['Does not want to build a %SnowMan %StopAsking', 'LOLZ BELLE.  %StockholmeSyndrome  %SnowMan']}}

Or, if we take the tag 'StockholmeSyndrome' , the new dictionary should look like this:

{'StockholmeSyndrome': {
        500: ["Actually nm. This isn't so bad lolz :P %StockholmeSyndrome"], 
        400: ['LOLZ BELLE.  %StockholmeSyndrome  %SnowMan']}}

In the end, the new dictionary needs to include all tags from the previous dictionary as keys, including the event in which there is no tag.

I'm really stuck on this one, can anyone offer some guidance?

Using collections.defualtdict you can iterate and append to lists in a nested dictionary structure:

from collections import defaultdict

dd = defaultdict(lambda: defaultdict(list))
for id_, text, tags, likes, dislikes in d.values():
    for tag in tags:
        dd[tag][id_].append(text)

print(dd)

defaultdict(<function __main__.<lambda>>,
            {'': defaultdict(list, {200: ['Make the ocean great again.']}),
             'JustSayNo': defaultdict(list,
                         {300: ['If some random dude offers to %ShowYouTheWorld do yourself a favour and %JustSayNo.']}),
             'OhNoes': defaultdict(list,
                         {500: ["Help I'm being held captive by a beast!  %OhNoes"]}),
             'ShowYouTheWorld': defaultdict(list,
                         {300: ['If some random dude offers to %ShowYouTheWorld do yourself a favour and %JustSayNo.']}),
             'SnowMan': defaultdict(list,
                         {400: ['Does not want to build a %SnowMan %StopAsking',
                           'LOLZ BELLE.  %StockholmeSyndrome  %SnowMan']}),
             'StockholmeSyndrome': defaultdict(list,
                         {400: ['LOLZ BELLE.  %StockholmeSyndrome  %SnowMan'],
                          500: ["Actually nm. This isn't so bad lolz :P %StockholmeSyndrome"]}),
             'StopAsking': defaultdict(list,
                         {400: ['Does not want to build a %SnowMan %StopAsking']})})

defaultdict is a subclass of dict , so you generally need no further manipulation. However, if you require a regular dict object, you can use a recursive function:

def default_to_regular_dict(d):
    """Convert nested defaultdict to regular dict of dicts."""
    if isinstance(d, defaultdict):
        d = {k: default_to_regular_dict(v) for k, v in d.items()}
    return d

res = default_to_regular_dict(dd)

print(res)

{'': {200: ['Make the ocean great again.']},
 'JustSayNo': {300: ['If some random dude offers to %ShowYouTheWorld do yourself a favour and %JustSayNo.']},
 'OhNoes': {500: ["Help I'm being held captive by a beast!  %OhNoes"]},
 'ShowYouTheWorld': {300: ['If some random dude offers to %ShowYouTheWorld do yourself a favour and %JustSayNo.']},
 'SnowMan': {400: ['Does not want to build a %SnowMan %StopAsking',
   'LOLZ BELLE.  %StockholmeSyndrome  %SnowMan']},
 'StockholmeSyndrome': {400: ['LOLZ BELLE.  %StockholmeSyndrome  %SnowMan'],
  500: ["Actually nm. This isn't so bad lolz :P %StockholmeSyndrome"]},
 'StopAsking': {400: ['Does not want to build a %SnowMan %StopAsking']}}

what about this ?

keys = ['name', 'last_name', 'phone_number', 'email']
dict2 = {x:dict1[x] for x in keys}

After reviewing your requirements I have updated my previous post with the code below. I believe this is what you are trying to achieve. The only import needed is an OrderedDict from the collections module.

from collections import OrderedDict
from pprint import PrettyPrinter as pp


str_tag_dict = {}
for v in d.values():
    str_tag_dict[v[1]] = v[2]

def same_tags_and_ids(str1, str2):
    dd = {str1:str_tag_dict[str1], 
          str2:str_tag_dict[str2]}
    tag = []
    v = dd[str1]
    for vv in v:
        for ks in dd.keys():
            if vv in dd[ks]:
                tag.append(vv)
                for tg in tag:
                    if tag.count(tg) > 1:
                        return tg
    return None

ordp = OrderedDict(sorted(d.items()))
def same_tags_diff_ids():
    x = []
    y = []
    my_str = []
    for v in ordp.values():
        x.append(v[2][0])
        x.append(v[0])
        x.append(v[1])
        for i in x:
            if x.count(i) > 1 and type(i) == str:
                y.append(i)
    for i in range(len(x)):
        if x[i] == list(set(y))[0]:
            my_str.append({list(set(y))[0]:{x[i + 1]:[x[i + 2]]}})
    d={}
    k1, v1 = list(my_str[0][list(my_str[0])[0]].items())[0]
    k2, v2 = list(my_str[1][list(my_str[1])[0]].items())[0]
    d.update({list(my_str[0].keys())[0]:{k1:v1, k2:v2}}) 
    if not d == None:
        return d
    else:
        return None
dup_tag_str = same_tags_diff_ids()

for k, v in ordp.items():
    del d[k]
    for tag in v[2]:
        d[tag] = {v[0]:[v[1]]}

ordp = OrderedDict(sorted(d.items()))
ids= [list(v.keys())[0] for v in ordp.values()]
strs= [list(v.values())[0][0] for v in ordp.values()]

x = 0
for n in range(len(ordp)):
    tmp_keys = []
    for k, v in ordp.items():
        if not strs[x] == list(v.values())[0][0]:
            if ids[x] == list(v.keys())[0]:
                key = same_tags_and_ids(strs[x], list(v.values())[0][0])
                if not key == None:
                    tmp_keys.append(key)
                    if tmp_keys.count(key) == 1:
                        continue
                    else:
                        ordp[key][list(v.keys())[0]].append(strs[x])
    x += 1
dx = dup_tag_str
dy = dict(ordp)
dy.update(dx)
pp().pprint(dy)               

output:

 {'': {200: ['Make the ocean great again.']},
 'JustSayNo': {300: ['If some random dude offers to %ShowYouTheWorld do '
                 'yourself a favour and %JustSayNo.']},
 'OhNoes': {500: ["Help I'm being held captive by a beast!  %OhNoes"]},
 'ShowYouTheWorld': {300: ['If some random dude offers to %ShowYouTheWorld 
  do yourself a favour and %JustSayNo.']},
 'SnowMan': {400: ['LOLZ BELLE.  %StockholmeSyndrome  %SnowMan',
               'Does not want to build a %SnowMan %StopAsking']},
 'StockholmeSyndrome': {400: ['LOLZ BELLE.  %StockholmeSyndrome %SnowMan'],
                        500: ["Actually nm. This isn't so bad lolz :P "
                          '%StockholmeSyndrome']},
 'StopAsking': {400: ['Does not want to build a %SnowMan %StopAsking']}}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM