dropWizard
dropWizard

Reputation: 3538

Searching for Key, Value in a list of dictionaries

Answer to the question:

After some help, I realized that it was breaking because it was scanning through the emails and while one email would have what I was looking for, the rest didn't, and thus caused it to break.

Adding in a Try/Except solved the problem. Just for historical sake incase anyone else looks for a similar problem, this is the code that worked.

try:
  if (item for item in list_of_dict if item['name'] == "From" and item['value'] == 'NAME1 <name@some_email.com>').next():
    print('has it')
  else:
    pass
except StopIteration:
  print("Not found")

This way it would be able to scan through each email and have error handling if it broke, but if it found it be able to print that I found what I was looking for.

Original question:

Code:

if (item for item in list_of_dict if item['name'] == "From" and item['value'] == 'NAME1 <name1@some_email.com>').next()

I'm getting a StopIteration error:

Traceback (most recent call last):
  File "quickstart1.py", line 232, in <module>
    main()
  File "quickstart1.py", line 194, in main
    if (item for item in list_of_dict if item['name'] == "From" and item['value'] == 'NAME1 <name1@some_email.com>').next():
StopIteration

This is my code:

if (item for item in list_of_dict if item['name'] == "From" and item['value'] == 'NAME1 <name1@some_email.com>').next():
      print('has it')
else:
  print('doesnt have it')

When I checked to see if I am putting in the iterator incorrectly, I did a lookup for item['value']:

print((item for item in list_of_dict if item['name'] == "From").next())

Returns:

{u'name': u'From', u'value': u'NAME1 <name1@some_email.com>'}
{u'name': u'From', u'value': u'NAME2 <name2@some_email.com>'}

Upvotes: 1

Views: 5060

Answers (3)

roadrunner66
roadrunner66

Reputation: 7941

dicts = [
     { "name": "Tom", "age": 10 },
     { "name": "Pam", "age": 7 },
      { "name": "Dick", "age": 12 }
   ]

super_dict = {}    # will be {'Dick': 12, 'Pam': 7, 'Tom': 10}
for d in dicts:
    super_dict[d["name"]]=d['age']

if super_dict["Tom"]==10:
    print 'hey, Tom is really 10'

Upvotes: 0

alecxe
alecxe

Reputation: 473863

Just add another condition via and:

next(item for item in dicts if item["name"] == "Tom" and item["age"] == 10)

Note that next() would throw a StopIteration exception if there is no match, you can either handle that via try/except:

try:
    value = next(item for item in dicts if item["name"] == "Tom" and item["age"] == 10)
    print(value)
except StopIteration:
    print("Not found")

Or, provide a default value:

next((item for item in dicts if item["name"] == "Tom" and item["age"] == 10), "Default value")

Upvotes: 2

MSeifert
MSeifert

Reputation: 152647

If you want to check if any dictionary contains it you could use the default argument of next:

iter = (item for item in list_of_dict if item['name'] == "From" and item['value'] == 'name <email>')

if next(iter, None) is not None: # using None as default
    print('has it')
else:
    print('doesnt have it')

but that would also exclude None regular items, so you could also use try and except:

try:
    item = next(iter)
except StopIteration:
    print('doesnt have it')    
else: 
    print('has it') # else is evaluated only if "try" didn't raise the exception.

But notice that a generator can only be used once, so recreate the generator if you want to use it again:

iter = ...
print(list(iter))
next(iter) # <-- fails because generator is exhausted in print

iter = ...
print(list(iter))
iter = ...
next(iter) # <-- works

Upvotes: 0

Related Questions