0

So let's suppose I have the following dictionary:

data = {
    'A': ['A1', 'A2', 'A3'],
    'B': ['B1', 'B2', 'B3'],
    }

The question is what is the best way to get the key of a given value. For instance, I want to get a key in dictionary which one's value contains A2:

def get_key_depending_on_value(value):
    for key in data.keys():
        if value in data[key]:
            return key
    return 'There is no such string in data\'s values'

result = get_key_depending_on_value('A2')
print(result) # prints A

I could have written such a function, but is it the best practice or python has something built in?

  • 1
    Maybe using `next`, e.g. `next(k for k, v in data.items() if "A2" in v)`? Definitely don't return some random string if the element is not found, better use `None` or `StopIteration`. What time complexity are you aiming at? – tobias_k Sep 06 '22 at 22:08
  • 1
    That is the exact opposite of what a dictionary is designed to do. If you need to do this frequently, you should maintain a second dict with the opposite linkages: `{'A1':'A', 'A2':'A',...`. – jasonharper Sep 06 '22 at 22:10
  • 1
    @IjazUrRahim, no it does not actually. I have already written that functionality in here, but my case a bit differs from those answers as I have list as a value in dictionary and trying to figure out is it the fastest way in terms of runtime processes to get the key – Python Django Sep 06 '22 at 22:10
  • @tobias_k right now, this is the most beautiful answer on this post. That's certainly gonna work, but I'll wait for others for any case. Thank you! – Python Django Sep 06 '22 at 22:13
  • @PythonDjango, I know there is no built-in function/method available for such a process yet. Almost all of the possibilities are mentioned in the above question thread. – Ijaz Ur Rahim Sep 06 '22 at 22:13
  • @jasonharper, yes I do need to do this frequently but doesn't it contradicts readability or any of principles of programming? – Python Django Sep 06 '22 at 22:14
  • @tobias_k, I guess, you can post an answer now. – Python Django Sep 06 '22 at 22:19
  • Your data is tiny, why do you care about speed? Any method is fast on such tiny data, including yours. – Kelly Bundy Sep 06 '22 at 23:43
  • @KellyBundy, it is obvious I wouldn't put a huge dictionary while creating a post on Stackoverflow. For information, https://stackoverflow.com/help/how-to-ask – Python Django Sep 06 '22 at 23:53
  • True, but if your actual use case is a huge dictionary, you'd additionally tell us about that. – Kelly Bundy Sep 06 '22 at 23:59
  • Managed to squeeze out ~2% more speed than with `for k, v in data.items()` on some larger test data I made up, but of course I have no idea whether it's like *your* larger data. (Not that 2% is much, might even be slower on a different system or Python version). – Kelly Bundy Sep 07 '22 at 00:26
  • @KellyBundy, dude I have written **let's suppose**. Why should I write about what I am going to do if it is quiet obvious as I am not going to spoil my post with huge dictionary or even worse with non-sense info that no-one would need. – Python Django Sep 07 '22 at 15:25
  • Because you said you're interested in the fastest way, which usually depends on the data. Different solutions might be the fastest for different data. So without knowing what your actual data is like, we can't even properly benchmark candidate solutions. – Kelly Bundy Sep 07 '22 at 15:53
  • So you thought I would want to get fastest way from extracting key from dict of 2 items? – Python Django Sep 07 '22 at 15:58
  • The key is that, 1. My first intention wasn't to figure out the fastest way, it was about best practices. 2. It would be great if those who answer suggested me 2 solutions (one with a tiny dict, the second case if it was huge) – Python Django Sep 07 '22 at 16:05

1 Answers1

1

I suggest you generate a new dictionary:

data = {
    'A': ['A1', 'A2', 'A3'],
    'B': ['B1', 'B2', 'B3'],
}
d = {}
for key, values in data.items():
    d.update({value: key for value in values})

Now you can just do d[value] to get the key.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268