[ Python: for each tuple in list, check if string in tuple ]
I know how to cycle through all tuples in a list. However, my problem is to see if a string is in a tuple within the list. I have constructed the following:
# where:
unformatted_returns = [('2015-6-10', u'88.48'), ('2015-6-9', u'86.73'), ('2015-6-8', u'86.15'), ('2015-6-5', u'86.05')]
date_new = '2015-6-8'
for n in unformatted_returns: # The problem is here
if str(date_new) in n[0]:
print "found date"
rate_of_return_calc(date, date_new)
pass
else:
print "date {0} not found".format(date_new)
day_accumulater(d, m, y, date_new, date)
The problem is that the first tuple in the cycle n in unformatted_returns
does not satisfy the condition, therefore it prints "not found". I don't want it do this obviously, because date_new
is actually in the list!
So, how do I get the program to cycle through each n
, then if all n
's do not satisfy containing date_new
then print "day not found"
?
Answer 1
Move the else
one level down. for
loops also take an else
suite, which is executed when you did not exit the loop early. Then add a break
:
for n in unformatted_returns:
if date_new == n[0]:
print "found date"
rate_of_return_calc(date, date_new)
break
else:
print "date {0} not found".format(date_new)
day_accumulater(d, m, y, date_new, date)
I've also cleaned up your test; you are matching n[0]
against a date string, you want them to be equal, not for one to be a substring of the other.
Now one of two things can happen:
date_new
is equal to the first element of one of the tuples. Thebreak
is executed, thefor
loop ends, and theelse
suite is skipped.date_new
is not equal to any of the first elements of the tuples. Thebreak
is never executed, the loop ends and theelse
suite is executed to show no match was found.
Demo:
>>> unformatted_returns = [('2015-6-10', u'88.48'), ('2015-6-9', u'86.73'), ('2015-6-8', u'86.15'), ('2015-6-5', u'86.05')]
>>> date_new = '2015-6-8'
>>> for n in unformatted_returns:
... if date_new == n[0]:
... print "found date"
... break
... else:
... print "date {0} not found".format(date_new)
...
found date
>>> date_new = '2015-6-7' # not in the list
>>> for n in unformatted_returns:
... if date_new == n[0]:
... print "found date"
... break
... else:
... print "date {0} not found".format(date_new)
...
date 2015-6-7 not found
This obviously would only ever find the first such matching element.
If you must process all matching elements, a flag is usually easiest:
found = False
for n in unformatted_returns:
if date_new == n[0]:
print "found date"
rate_of_return_calc(date, date_new)
found = True
if not found:
print "date {0} not found".format(date_new)
day_accumulater(d, m, y, date_new, date)
All this assumes that n[1]
is of interest too. If all you need to know if the date is present, use any()
and a generator expression to test for a matching element:
if any(n[0] == date_new for n in unformatted_returns):
print "found date"
rate_of_return_calc(date, date_new)
else:
print "date {0} not found".format(date_new)
day_accumulater(d, m, y, date_new, date)
Now we won't know which n
matched, but that doesn't actually matter.
Answer 2
Just use a flag:
unformatted_returns = [('2015-6-10', u'88.48'), ('2015-6-9', u'86.73'), ('2015-6-8', u'86.15'), ('2015-6-5', u'86.05')]
date_new = '2015-6-8'
found_one = False
for n in unformatted_returns: # The problem is here
if str(date_new) in n[0]:
print "found date"
rate_of_return_calc(date, date_new)
found_one = True
# add a break here if you are only interested in the first match
if not found_one:
print "date {0} not found".format(date_new)
day_accumulater(d, m, y, date_new, date)
Answer 3
Just search for matches and if the search comes with no results, nothing was found:
matching_returns = [ur for ur in unformatted_returns if date_new == ur[0]]
if not matching_returns:
print "date {0} not found".format(date_new)
else:
# do something with matching_returns