简体   繁体   中英

Accessing value in a dict ignoring the key's second value

I have a dictionary L, whose keys are tuple of length 2: the first element is an index, the second element is either 0 or 1. I'm defining several functions. In one of them, I need to consider the second element of the tuple, therefore I need it to stay there. But now I have trouble in another function, in which I do not care at all about it. I have to retrieve the dict value of a given index (first element of the tuple), but I have no idea if the second value is a 0 or a 1. Is there a mute variable, or something that I can pass and it says "either 0 or 1"?

To make things clearer, I would like to have something like:

needed_value = L.get((given_index, either))

where "either" could be 0 or 1.

For now, I created an if/else, but it seems stupid, because both their body just assign the value.

Thank you very much, I hope I didn't miss a preexisting solution for this problem!

Edit:

My dict is something like:

L = {(7, 1): 0, (2, 0): 1, (5, 1): 4, (1, 1): 2, (11, 0): 3}

So, I know for sure that the second value in the keys is 0 or (exclusive) 1. Moreover, the first value is unique (if it is relevant).

The code with if/else was (more or less, I do not have it anymore):

if (i, 1) in L.keys():
            tau = L.get((i, 1))

elif (i, 0) in L.keys():
            tau = L.get((i, 0))

No, there's no way to do this. If you need to retrieve elements by the first part only, then you should make that the key and store the other part in the value.

No. Dictionary keys are hashed and you can't query them database-style with partial tuple matches.

What you can do, if you are sure that either 0 or 1 exists (but, for clarity and in Python <3.6, not both), is to use the optional fallback argument of dict.get :

L = {(10, 1): 5, (10, 2): 6, (10, 3): 7}

val = L.get((10, 0), L.get((10, 1)))

print(val)  # 5

Alternatively, and to account for the case when both (10, 0) and (10, 1) exist, you can use a custom function:

L = {(10, 1): 5, (10, 2): 6, (10, 3): 7, (10, 0): 8}

def get_val(x, key):
    try:
        return x[(key, 0)]
    except KeyError:
        return x[(key, 1)]

val = get_val(L, 10)

print(val)  # 8

Assuming you have something like this:

L = {(10, 1): 5, (10, 0): 6, (20, 0): 7}

And you want to get all the values that correspond to keys starting with, eg, 10 , aka (10, 0) and (10, 1)

to_match = 10

You can do:

res = [v for k, v in L.items() if any(k == (to_match, x) for x in (0, 1))]

which returns:

[5, 6]

As everyone already mentionned, you can't do this out of the box. Now if you need both ways to get the value(s) - one from the full key and another from a "partial" key, a solution might be to maintain a key[0]=>[keys...] mapping in parallel, ie:

L = {(10, 1): 5, (10, 0): 6, (20, 0): 7}
index = defaultdict(list)
for key in L:
    index[key[0]].append(key)

Then you can get the list of "complete" keys for a partial one

keys = index.get(10)
values = [L[k] for k in keys]

Of course this means you have to make sure you keep your index up to date so you would need to wrap this all in a class to make sure all updates to L are reflected in index .

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