-1

How would the following be achieved using comprehension so that bad_keys only contains the keys where the length of the associated value is 0?

def _check_data_for_length(self) -> []:
    """
        checks the lengths of the values contained within the dictionary of members
        returns a list of the keys containing data of length 0.
    :return: [] keys of empty values
    """
    bad_keys = []
    for (key, value) in vars(self).items():
        if len(value) == 0:
            bad_keys.append(key)
    return bad_keys
khelwood
  • 55,782
  • 14
  • 81
  • 108
eklektek
  • 1,083
  • 1
  • 16
  • 31
  • 5
    `bad_keys = [key for key, value in vars(self).items() if len(value) == 0]` – 001 Jan 20 '23 at 13:46
  • Is the problem that you are getting due to some objects not having a length, i.e., if they are just numbers? – Matt Pitkin Jan 20 '23 at 13:47
  • 1
    If so, you could just put a `try... except...` around the `if len(value) == 0: bad_keys.append(key)` – Matt Pitkin Jan 20 '23 at 13:48
  • 1
    if `value` has a `len()` you can typically simplify to `bad_keys = [key for key, value in vars(self).items() if value]` – JonSG Jan 20 '23 at 13:50
  • @JohnnyMopp correcting your syntax, adding brackets giving -- `bad_keys = [key for (key, value) in vars(self).items() if len(value) == 0]` does return what I'm expecting. Appreciated. – eklektek Jan 20 '23 at 13:59
  • The original syntax was already correct… – deceze Jan 20 '23 at 14:01
  • thanks @deceze now I'm confused it now seems to work either with or without the brackets thanks for pointing this out. – eklektek Jan 20 '23 at 14:07
  • whoever marked this question down, please explain how it is not adding value to stack overflow? – eklektek Jan 20 '23 at 14:37
  • Have you attempted to write this as a comprehension and where did you get stuck? – deceze Jan 20 '23 at 14:38
  • I was putting the if clause prior to the for, having viewed something on YouTube, big mistake. – eklektek Jan 20 '23 at 14:42
  • Then the better question would have been to post that attempt and clarify the problem with it. – deceze Jan 20 '23 at 14:43

1 Answers1

1

If you just want to return the bad keys of things that have a length, then you could do (edited based on the comment by @deceze):

x = {"a": 1, "b": [3., 4.], "c": []}

badkeys = [k for k, v in x.items() if hasattr(v, '__len__') and len(v) == 0]

which gives:

['c']
Matt Pitkin
  • 3,989
  • 1
  • 18
  • 32
  • 1
    `[k for k, v in x.items() if hasattr(v, '__len__') and len(v) == 0]`…?! – deceze Jan 20 '23 at 14:02
  • Yes, that's more succinct. I'll edit it. I wasn't sure about the precedence of things in conditions and where `len(v)` would get called even if the `hasattr(v, '__len__')` was False. – Matt Pitkin Jan 20 '23 at 14:03
  • 1
    `and` operator short-circuiting still works the same as elsewhere. – deceze Jan 20 '23 at 14:06