[Tutor] How do I (idiomatically) determine when I'm looking at the last entry in a list?
Afternoon, Python 3. I'm iterating through a list and I'd like to know when I'm at the end of the said list, so I can do something different. For example list_of_things = ['some', 'special', 'things'] for each_entry in list_of_things: print(each_entry) if each_entry == list_of_things[-1]: # do something special to last entry ...etc Is this the idiomatic way to detect you're at the last entry in a list as you iterate through it? For context, I'm working my way through a (csv) file which describes some database tables. I'm building the Oracle DDL to create that table as I go. When I find myself building the last column, I want to finish the definition with a ");" rather than the usual "," which occurs at the end of all other column definitions... e.g. CREATE TABLE wibble ( Col1CHAR(2), Col2NUMBER(5,2), ); Regards, Steve. This email is security checked and subject to the disclaimer on web-page: http://www.capita.co.uk/email-disclaimer.aspx ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] How do I (idiomatically) determine when I'm looking at the last entry in a list?
Flynn, Stephen (L & P - IT) wrote: > Afternoon, > > Python 3. > > I'm iterating through a list and I'd like to know when I'm at > the end of the said list, so I can do something different. For example > > list_of_things = ['some', 'special', 'things'] > for each_entry in list_of_things: > print(each_entry) > if each_entry == list_of_things[-1]: # do something special to > last entry > ...etc > > > Is this the idiomatic way to detect you're at the last entry in a list > as you iterate through it? If the list is small you can slice it: assert items for item in things[:-1]: print(item, ",", sep="") print(items[-1]) I have written a generator similar to >>> def g(items): ... items = iter(items) ... try: ... prev = next(items) ... except StopIteration: ... return ... for item in items: ... yield False, prev ... prev = item ... yield True, prev ... >>> for islast, item in g("abc"): ... print(item, "(done)" if islast else "(to be continued)", sep="") ... a(to be continued) b(to be continued) c(done) but only used it once ore twice. > For context, I'm working my way through a (csv) file which describes > some database tables. I'm building the Oracle DDL to create that table > as I go. When I find myself building the last column, I want to finish > the definition with a ");" rather than the usual "," which occurs at the > end of all other column definitions... > > e.g. > CREATE TABLE wibble > ( > Col1 CHAR(2), > Col2 NUMBER(5,2), > ); This particular problem can idiomatically be addressed with str.join(): >>> print(",\n".join(["foo", "bar", "baz"])) foo, bar, baz ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] How do I (idiomatically) determine when I'm looking at the last entry in a list?
On 28Oct2015 14:48, Flynn, Stephen (L & P - IT)wrote: Python 3. I'm iterating through a list and I'd like to know when I'm at the end of the said list, so I can do something different. For example list_of_things = ['some', 'special', 'things'] for each_entry in list_of_things: print(each_entry) if each_entry == list_of_things[-1]: # do something special to last entry ...etc Is this the idiomatic way to detect you're at the last entry in a list as you iterate through it? If it really is a list then enumerate is your friend. list_of_things = ['some', 'special', 'things'] last_index = len(list_of_things) - 1 for index, each_entry in enumerate(list_of_things): print(each_entry) if index == last_index: ... special stuff for the last index ... For context, I'm working my way through a (csv) file which describes some database tables. I'm building the Oracle DDL to create that table as I go. When I find myself building the last column, I want to finish the definition with a ");" rather than the usual "," which occurs at the end of all other column definitions... This is a bit different, in that you are probably not using a list: you don't know how long the sequence is. I build things like that this way: fp.write('CREATE TABLE wibble\n(') sep = '\n ' for item in items: fp.write(sep) fp.write(... column definition for item ...) sep = ',\n ' fp.write('\n);\n') i.e. instead of printing the separator _after_ each item, print it _before_. That way you can special case the first occasion and use a comma for each successive occasion. Cheers, Cameron Simpson Why is it whatever we don't understand is called a 'thing'? - "Bones" McCoy ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] How do I (idiomatically) determine when I'm looking at the last entry in a list?
On Wed, Oct 28, 2015 at 02:48:05PM +, Flynn, Stephen (L & P - IT) wrote: > I'm iterating through a list and I'd like to know when I'm at > the end of the said list, so I can do something different. For example > > list_of_things = ['some', 'special', 'things'] > for each_entry in list_of_things: > print(each_entry) > if each_entry == list_of_things[-1]: # do something special to > last entry > ...etc > > > Is this the idiomatic way to detect you're at the last entry in a list > as you iterate through it? But it doesn't detect the last entry. Consider: list_of_things = ["cheese", "fruit", "cheese", "fish", "cheese"] Your code will perform the special processing three times. There's no idiomatic way to do this because it is a fairly unusual thing to do. Normally we want to process all the items in a list the same way. But here are some solutions: (1) Avoid the problem altogether by arranging matters so that the "last item" isn't in the list at all. list_of_things = ['some', 'special'] last = 'things' for each_entry in list_of_things: print(each_entry) print(last.upper()) (2) Slicing. Requires a little extra memory, but is probably the closest to an idiomatic solution for this sort of thing. list_of_things = ['some', 'special', 'things'] for each_entry in list_of_things[:-1]: print(each_entry) print(list_of_things[-1].upper()) (3) Add a sentinel to the list. list_of_things = ['some', 'special', None, 'things'] for each_entry in list_of_things: if each_entry is None: break print(each_entry) print(list_of_things[-1].upper()) (4) Count the items. list_of_things = ['some', 'special', 'things'] for i, each_entry in enumerate(list_of_things): if i == len(list_of_things) - 1: # Watch out for off-by-one errors! each_entry = each_entry.upper() print(each_entry) (5) What if you're dealing with an iterable of unknown length that can't be sliced? The obvious answer is to convert to a list: list_of_things = list(things) but suppose you have some reason for not wanting to do that. (Perhaps things is truly huge, billions of items.) Something like this should help: prev = [] for this in things: if prev: print(prev[0]) prev = [this] print(prev[0].upper()) We can make this a little more efficient if things is an actual iterator: things = iter(things) try: prev = next(things) except StopIteration: # No things at all. pass else: for this in things: print(prev) prev = this print(prev.upper()) -- Steve ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] How do I (idiomatically) determine when I'm looking at the last entry in a list?
Wait, I have another comment... On Wed, Oct 28, 2015 at 02:48:05PM +, Flynn, Stephen (L & P - IT) wrote: > I'm iterating through a list and I'd like to know when I'm at > the end of the said list, so I can do something different. For example [...] > For context, I'm working my way through a (csv) file which describes > some database tables. I'm building the Oracle DDL to create that table > as I go. When I find myself building the last column, I want to finish > the definition with a ");" rather than the usual "," which occurs at the > end of all other column definitions... Then you don't need to know when you're at the end of the list. See below. But firstly, and MOST IMPORTANTLY, how are you sanitizing your input? http://bobby-tables.com/ Code injection attacks are now #1 risk factor for code, above buffer overflows. So, assuming you have sanitized your input, or trust it more than you trust your own code (you run tests on your own code, right?), let's see how to build up a string like: "FUNCTION(a,b,c,d,e);" with some variable number of string arguments a, b, c, ... args = ["5", "2", "7", "1", "0", "3"] result = "FUNCTION(%s);" % ','.join(args) This will do the right thing whether there is one argument or twenty, or even no arguments at all. The "join" method inserts the first string *between* each of the list items. It deals correctly with the "no items" and "one item" cases: py> "--".join([]) '' py> "--".join(["spam"]) 'spam' py> "--".join(["spam", "eggs"]) 'spam--eggs' py> "--".join(["spam", "eggs", "cheese"]) 'spam--eggs--cheese' so you don't have to worry about counting items or determining the last item, you just join them. -- Steve ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor