1

I have generator cut_slices and use for loop. But I need to do some specific work with the first and last yielding elements outside the loop. With first it's easy, just use next() before loop. But what with last?


fu_a = self.cut_slices(unit, unit_size) #generator (simple for loop with some calculations and yield)

header = self.make_header(p=0, first_byte=unit[0], rtp_type=rtp_type, flag='s')
self.send_packet(header + next(fu_a))

for i in fu_a: #if there is an analogue of a[:-1] for generator object?
    header = self.make_header(p=0, first_byte=unit[0], rtp_type=rtp_type,
                              flag='m')
    self.send_packet(header + i)

header = self.make_header(p=0, first_byte=unit[0], rtp_type=rtp_type, flag='e')
self.send_packet(header + next(fu_a))

P.S. I understand that there are other ways to achieve the same result, just want to figure out.

  • 1
    If you put each element in a variable, so that the variable always has just the last one generated, when the loop is over, ... – Scott Hunter Nov 07 '19 at 20:03
  • You can keep track of the last item per iteration, so, before next iteration, update last item with current one. – dcg Nov 07 '19 at 20:03
  • check [this so question](https://stackoverflow.com/questions/2138873/cleanest-way-to-get-last-item-from-python-iterator) Cleanest way to get last item from Python iterator – eguaio Nov 07 '19 at 20:03

2 Answers2

1

In the below code, run your intended function on aa in the for loop, and disregard the last function call. After the end of loop, you'll have your variable as aa

In [1]: a = (i for i in range(10))
In [2]: first = next(a)
In [3]: first
Out[3]: 0
In [4]: for aa in a:
   ...:     print(aa)
   ...:
1
2
3
4
5
6
7
8
9
In [5]: aa
Out[5]: 9

After reading a medium article on a similar topic, I found a better way to get the last val:

In [29]: def get_last_val(A):
    ...:     v = next(A)
    ...:     for a in A:
    ...:         yield False, v
    ...:         v = a
    ...:     yield True, v

In [30]: a = (i for i in range(10))

In [31]: a = get_last_val(a)

In [32]: for aa in a:
    ...:     print(aa)
    ...:
(False, 0)
(False, 1) 
(False, 2)
(False, 3)
(False, 4)
(False, 5)
(False, 6)
(False, 7)
(False, 8)
(True, 9)

If the first return value is True, that would be the last value in the iteration.

Osman Mamun
  • 2,864
  • 1
  • 16
  • 22
0

If it doesn't cause memory problems, just make a list of everything returned by the generator, and slice that.

fu_a = self.cut_slices(unit, unit_size) #generator (simple for loop with some calculations and yield)

header = self.make_header(p=0, first_byte=unit[0], rtp_type=rtp_type, flag='s')
self.send_packet(header + next(fu_a))

*middle_fu, last_fu = list(fu_a)

for i in middle_fu:
    header = self.make_header(p=0, first_byte=unit[0], rtp_type=rtp_type,
                              flag='m')
    self.send_packet(header + i)

header = self.make_header(p=0, first_byte=unit[0], rtp_type=rtp_type, flag='e')
self.send_packet(header + last_fu)
Barmar
  • 741,623
  • 53
  • 500
  • 612