3

I have a dictionary:

classes_dictionary = {'/m/09x0r': 'Speech', '/m/03qc9zr': 'Screaming'}

and a list:

labels_list = ['/m/03k3r', '/m/04rlf', '/m/07q5rw0', '/m/09x0r', '/m/0jbk']

labels_list will always contain at least one element which is a key of classes_dictionary. I wish to extract which classes are those with the lowest computational complexity. In this example, '/m/09x0r' will be translated into 'Speech'. my solution:

class_str = list()
for k in labels_list:
    print(k)
    if k in self.classes_dictionary:
        class_str.append(self.classes_dictionary[k])

I do not mind if the output is a list or any other type. Also, for generality of the question I am assuming only a single element of labels_list is a key, though the best answer may consider both cases.

Is there a more efficient way to implement this? I am asking on both, implementation efficiency

kederrac
  • 16,819
  • 6
  • 32
  • 55
havakok
  • 1,185
  • 2
  • 13
  • 45

6 Answers6

1

You can use get() and check if the returned value is not None instead of looking if the key exists in the dict (although it's O(1) operation). If you know it's only one value add break

class_str = []
for k in labels_list:
    value = classes_dictionary.get(k)
    if value:
        class_str.append(value)

If you are using Python 3.8 you can use Assignment Expressions, which will evaluate classes_dictionary.get(x) only once

class_str = [y for x in labels_list if (y := classes_dictionary.get(x)) is not None]
Guy
  • 46,488
  • 10
  • 44
  • 88
1

Using a list comprehension:

>>> [classes_dictionary[k] for k in labels_list if k in classes_dictionary]
['Speech']

If only one match is expected, you can use next with a generator expression to stop searching once it's found:

>>> next(classes_dictionary[k] for k in labels_list if k in classes_dictionary)
'Speech'
kaya3
  • 47,440
  • 4
  • 68
  • 97
0

To be for efficent check key on dict.

#YOUR CODE
if k in self.classes_dictionary:
    #do_job

#More efficient
try:
    self.classes_dictionary[k]
    #do_job
except:
    #Key not in dict
    pass
Wonka
  • 1,548
  • 1
  • 13
  • 20
  • This is not more efficient unless the vast majority of the keys are actually present in the dictionary - see [this answer](https://stackoverflow.com/a/2522013/12299000): *"try/except is faster than an explicit if as long as the condition is not met. [...] Only if the condition is actually met, then the if version is significantly faster."* According to the OP, only one key is expected to actually be in the dictionary, so this is a case where try/except is significantly slower. – kaya3 Feb 19 '20 at 12:03
0

Currently your labels_list consists of one string. It seems it should be a list of 5 strings. You do not need self. in front of classes_dictionary:

class_str = list()
for k in labels_list:
  print(k)
  if k in classes_dictionary:
    class_str.append(classes_dictionary[k])
GLarose
  • 171
  • 1
  • 9
0

If labels_list is a set instead, you might be able to squeeze out some performance. Use intersection of set and dictionary keys:

classes_dictionary = {'/m/09x0r': 'Speech', '/m/03qc9zr': 'Screaming'}
labels_list= set(['/m/03k3r', '/m/04rlf', '/m/07q5rw0', '/m/09x0r', '/m/0jbk'])

[classes_dictionary[k] for k in labels_list & classes_dictionary.keys()]
busybear
  • 10,194
  • 1
  • 25
  • 42
  • Testing set membership is the same efficiency as testing dictionary membership, so you can replace the intersection with `if k in classes_dictionary` here. – kaya3 Feb 19 '20 at 12:00
0

you could use the intersection of the dict keys with the elements from labels_list in a list comprehension:

class_str = [classes_dictionary[e] for e in set(classes_dictionary).intersection(labels_list)]

output:

['Speech']
kederrac
  • 16,819
  • 6
  • 32
  • 55