简体   繁体   中英

Get key by more than one value in dictionary?

Maybe the dict is not intended to be used in this way, but I need to add more than one value to the same key. My intension is to use a kind of transitory property. If my dict is A:B and B:C , than I want to have the dict A:[B,C] .

Let's make an example in order to explain better what I'd like to do:

numDict={'60':['4869'], '4869':['629'], '13':['2']}

I want it to return:

{'60':['4869','629'], '13':['2']}

For just two elements, it is possible to use something like this:

result={}
for key in numDict.keys():
    if [key] in numDict.values():
        result[list(numDict.keys())[list(numDict.values()).index([key])]]=[key]+numDict[key]

But what about if I have more elements? For example:

numDict={'60':['4869'], '4869':['629'], '13':['2'], '629':['427'}

What can I do in order to get returned {'60':[4869,629,427'], '13':['2']} ?

I have written a code for it. See if it helps.

What I have done is to go on diving in till i can go (hope you understand this statement) and mark them as visited as they will no longer be required. At the end I filter out the root keys.

numDict={'60':['4869'], '4869':['629'], '13':['2'], '629':['427']}

l = list(numDict) # list of keys
l1 = {i:-1 for i in numDict} # to track visited keys (initialized to -1 initially)

for i in numDict:
    # if key is root and diving in is possible
    if l1[i] == -1 and numDict[i][0] in l:
        t = numDict[i][0]
        while(t in l): # dive deeper and deeper
            numDict[i].extend(numDict[t]) # update the value of key
            l1[t] = 1 # mark as visited
            t = numDict[t][0]
# filter the root keys
answer = {i:numDict[i] for i in numDict if l1[i] == -1}
print(answer)

Output:

{'60': ['4869', '629', '427'], '13': ['2']}
def unchain(d):
    #assemble a collection of keys that are not also values. These will be the keys of the final dict. 
    top_level_keys = set(d.keys()) - set(d.values())

    result = {}
    for k in top_level_keys:
        chain = []
        #follow the reference chain as far as necessary.
        value = d[k]
        while True:
            if value in chain: raise Exception("Referential loop detected: {} encountered twice".format(value))
            chain.append(value)
            if value not in d: break
            value = d[value]           
        result[k] = chain
    return result

numDict={'60':'4869', '4869':'629', '13':'2', '629':'427'}
print(unchain(numDict))

Result:

{'60': ['4869', '629', '427'], '13': ['2']}

You might notice that I changed the layout of numDict since it's easier to process if the values aren't one-element lists. But if you're dead set on keeping it that way, you can just add d = {k:v[0] for k,v in d.items()} to the top of unchain , to convert from one to the other.

You can build your own structure, consisting of a reverse mapping of (values, key) , and a dictionary of (key, [values]) . Adding a key, value pair consists of following a chain of existing entries via the reverse mapping, until it finds the correct location; in case it does not exist, it introduces a new key entry:

class Groupir:
    def __init__(self):
        self.mapping = {}
        self.reverse_mapping = {}

    def add_key_value(self, k, v):
        self.reverse_mapping[v] = k
        val = v
        key = k
        while True:
            try:
                self.reverse_mapping[val]
                key = val
                val = self.reverse_mapping[val]
            except KeyError:
                try:
                    self.mapping[val].append(v)
                except KeyError:
                    self.mapping[val] = [v]
                break

with this test client:

groupir = Groupir()
groupir.add_key_value(60, 4869)
print(groupir.mapping)
groupir.add_key_value(4869, 629)
print(groupir.mapping)
groupir.add_key_value(13, 2)
print(groupir.mapping)
groupir.add_key_value(629, 427)
print(groupir.mapping)

outputs:

{60: [4869]}
{60: [4869, 629]}
{60: [4869, 629], 13: [2]}
{60: [4869, 629, 427], 13: [2]}

Restrictions:

Cycles as mentioned in comments.
Non unique keys
Non unique values
Probably some corner cases to take care of.

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