1

Can anybody help me. my question is in the code comments. I want to check if the generator items is empty.

name = 'john'
while True:
   n = (x for x in names if x['name'] == name) #generator
   if len(n) != 0: #this is wrong obviously. But this is what I want to do with the generator items.
      break
   name = input('Enter name > ')
mark12345
  • 233
  • 1
  • 4
  • 10
  • Is the purpose of the iterator only to check if the name is found? – bereal Jul 14 '21 at 11:28
  • yes. But if not found, it should ask again to enter another name from available names – mark12345 Jul 14 '21 at 11:29
  • If that's your usecase (and not just example), then on `next` or whatever check you use, python will evaluate it anyway. So just use loop to check the containing (to exit early with first) or make this n a list instead of generator. – h4z3 Jul 14 '21 at 11:30
  • Yeah I have no choice but to use list again. since I want to get the last and first and count the items. I thought it will be easily possible with generator – mark12345 Jul 14 '21 at 11:33

2 Answers2

3

Call next(<generator>, None) on it and check for the result not being None, or use your custom value if you expect None as a part of the generator output.

Alternatively, don't, but catch the StopIteration:

try:
    next(<generator>)
except StopIteration:
    print("I'm empty")
Peter Badida
  • 11,310
  • 10
  • 44
  • 90
  • 1
    Or as Python does: "better ask for forgiveness" - just do `next(gen)` and catch – h4z3 Jul 14 '21 at 11:28
  • @h4z3 exactly :) Though multiple of try/except are ugly, but that's a matter of preference/readability. – Peter Badida Jul 14 '21 at 11:29
  • Thanks for this answer, But it will skip the first item right? that's what I'm still confused about using next. Since my result should be only 1 item – mark12345 Jul 14 '21 at 11:30
  • but i will try this :) – mark12345 Jul 14 '21 at 11:31
  • @mark12345 `next(x for x in ["first"])` outputs `"first"`, so it won't "skip" it, but if you intend to use the generator later on you'll need to [do something else too](https://stackoverflow.com/a/1271481/5994041). – Peter Badida Jul 14 '21 at 11:33
  • Oh I'm gonna check it out. I actually like to use generator specially this is huge data. – mark12345 Jul 14 '21 at 11:37
  • 1
    Thank you. I found this usefull. I used next(gen, None) instead. So I can still use While loop and ask the user to input if gen is None – mark12345 Jul 14 '21 at 22:07
2

It seems that the purpose of the iterator is to find that whether the name is known. If it's the case, you can use any:

if any(x['name'] == name for x in names):
    break

Or even shorter without break:

while all(x['name'] != name for x in names):
    name = input('Enter name > ')
    
bereal
  • 32,519
  • 6
  • 58
  • 104
  • I wanted to suggest this but with `x for x in...`, OP gets empty or x. `any` would only say *if* they got it there, not fetch the element – h4z3 Jul 14 '21 at 11:31
  • @h4z3 the OP is not using the found element anyway. – bereal Jul 14 '21 at 11:32
  • In this code snippet, yes. But as `x` is some bigger struct and OP's looking for a matching one, then I think it's safe to assume they want to use it afterwards – h4z3 Jul 14 '21 at 11:34
  • That's better idea. but how I can fetch the element if it is found? – mark12345 Jul 14 '21 at 11:35
  • @TomKarzes `names` is not a list of `str`, it's a list of `dict`, so `name in names` won't work. – bereal Jul 14 '21 at 12:01
  • @mark12345 if you want to fetch the element, then Peter's answer is better. – bereal Jul 14 '21 at 12:04
  • @TomKarzes it's a list of dicts, not a dict. We're finding a dict with a given key-value. – bereal Jul 14 '21 at 12:07
  • @bereal yes that's what actually what I want. My question is incomplete (because I don't know yet earlier what exactly the right question) if the name is found in the list, I will fetch the items or index not only the name. – mark12345 Jul 14 '21 at 12:38
  • @mark12345 depending on context, it may get simpler if you create another lookup dict `by_name = {x['name']: x for x in names}` – bereal Jul 14 '21 at 12:40
  • @bereal I must be tired - sorry for all the confusion. Nice King Crimson avatar ;) – Tom Karzes Jul 14 '21 at 13:09