Is there a pythonic way of knowing when the first and last loop in for passes?

I have a template in which I put, say, 5 forms, but all are disabled for publication, except for the first. The following form can only be completed if I click on the button that allows it first.

I am looking for a way to implement a Django-like variable forloop.last templatetag in a for loop inside an acceptance test to decide whether to execute a method that includes the following form or not.

Basically, I need to do something like:

for form_data in step.hashes: # get and fill the current form with data in form_data if not forloop.last: # click the button that enables the next form # submit all filled forms 
+6
source share
6 answers

If I understand your question correctly, you need a simple test: are you at the beginning or end of the list?

If this happens, it would do this:

 for item in list: if item != list[-1]: #Do stuff 

For the first item in the list, you replace "-1" with 0.

0
source

I don't know anything built-in, but you can easily write a generator to provide the necessary information:

 def firstlast(seq): seq = iter(seq) el = prev = next(seq) is_first = True for el in seq: yield prev, is_first, False is_first = False prev = el yield el, is_first, True >>> list(firstlast(range(4))) [(0, True, False), (1, False, False), (2, False, False), (3, False, True)] >>> list(firstlast(range(0))) [] >>> list(firstlast(range(1))) [(0, True, True)] >>> list(firstlast(range(2))) [(0, True, False), (1, False, True)] >>> for count, is_first, is_last in firstlast(range(3)): print(count, "first!" if is_first else "", "last!" if is_last else "") 0 first! 1 2 last! 
+4
source

You can use enumerate and compare the counter with the list length:

 for i, form_data in enumerate(step.hashes): if i < len(step.hashes): whatever() 
+2
source
 for form_data in step.hashes[:-1]: # get and fill the current form with data in form_data for form_data in step.hashes[-1:]: # get and fill the current form with data in form_data # click the button that enables the next form # submit all filled forms 

Don't like the repetition of get and fill the current form with data in form_data ? Define a function.

+2
source

Generator with a buffer.

 def first_last( iterable ): i= iter(iterable) f= next(i) yield f, "first" n= next(i) for another in i: yield n, None n= another yield n, "last" for item, state in first_list( iterable ): # state is "first", None or "last". 

Replacing two sequences

 flags = ["first"] + (len(iterable)-2)*[None] + ["last"] for item, state in zip( iterable, flags ): # state is "first", None or "last". 
+2
source

I think he wants to have a wrapper around the iterator that provides the first / last requests, the iterator can also be a parameter, so all kinds of len () will not work

This is what I came up with, the trick is to use a double iterator that looks to the future one step of the first:

 class FirstLastIter(object): def __init__(self, seq): self._seq_iter = iter(seq) self._seq_iter_next = iter(seq) self._idx = -1 self._last = None self.next_next() @property def first(self): return self._idx == 0 @property def last(self): return self._last == True def __iter__(self): return self def next_next(self): try: self._seq_iter_next.next() except StopIteration: self._last = True def next(self): val = self._seq_iter.next() self._idx += 1 self.next_next() return val for x in FirstLastIter([]): print x iterator = FirstLastIter([1]) for x in iterator: print x,iterator.first,iterator.last iterator = FirstLastIter([1,2,3]) for x in iterator: print x,iterator.first,iterator.last 

returns:

 1 True True 1 True False 2 False False 3 False True 
0
source

Source: https://habr.com/ru/post/897005/


All Articles