Python: for each tuple in list, check if string in tuple

905 views Asked by At

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"?

3

There are 3 answers

1
Martijn Pieters On BEST ANSWER

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. The break is executed, the for loop ends, and the else suite is skipped.

  • date_new is not equal to any of the first elements of the tuples. The break is never executed, the loop ends and the else 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.

0
Steve Barnes On

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)
0
Steven Rumbalski On

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