Last iteration condition

Hi,

   How could I know that current iteration is the last in the series?
   For example:

[1, 2, 3, 4, 5, 3, 4].each do |element|
   print element.to_s
   print ',' if !LAST
end

P.S. This is just an example. I don't want to use "join". My program
logic is much complicated than this example.

Thank you.

ri each_with_index

···

On Apr 2, 8:56 pm, "Mike" <michae...@gmail.com> wrote:

   How could I know that current iteration is the last in the series?
   For example:

[1, 2, 3, 4, 5, 3, 4].each do |element|
   print element.to_s
   print ',' if !LAST
end

Here are a couple of ideas:

require 'generator'
require 'enumerator'

a = [1,2,3,4]
g = Generator.new(a)

while g.next?
   item = g.next
   if g.next?
     puts "#{item} is not the last item"
   else
     puts "#{item} is the last item"
   end
end

a = [5,6,7,8]
a.push(final = Object.new)

Enumerable::Enumerator.new(a).each_cons(2) do |a, b|
   if b == final
     puts "#{a} is the last item"
   else
     puts "#{a} is not the last item"
   end
end

# Gary Wright

···

On Apr 2, 2007, at 11:00 PM, Mike wrote:

Hi,

   How could I know that current iteration is the last in the series?
   For example:

[1, 2, 3, 4, 5, 3, 4].each do |element|
   print element.to_s
   print ',' if !LAST
end

a = [1, 2, 3, 4, 5, 3, 4]
a.each_with_index do |element,i|
   print element.to_s
   print ',' if i == a.length - 1
end

···

On Apr 2, 7:56 pm, "Mike" <michae...@gmail.com> wrote:

   How could I know that current iteration is the last in the series?

Try this. It should print out "1,2,3,4,5,3,4" as desired.

arr = [1, 2, 3, 4, 5, 3, 4]
arr.each_with_index do |element, index|
   print element.to_s
   print "," unless arr.length == index + 1
end

Cheers,
Luis
http://www.luisdelarosa.com

···

On Apr 2, 2007, at 11:00 PM, Mike wrote:

Hi,

   How could I know that current iteration is the last in the series?
   For example:

[1, 2, 3, 4, 5, 3, 4].each do |element|
   print element.to_s
   print ',' if !LAST
end

P.S. This is just an example. I don't want to use "join". My program
logic is much complicated than this example.

Thank you.

[1, 2, 3, 4, 5, 3, 4].each_index do |index|
   print ',' if index > 0
   print element[index].to_s
#-- or -- if the logic "print ',' " is actually dependent on the
values of the elements
   print element[index-1].to_s
end

~~LF

···

On 4/2/07, Mike <michaelst@gmail.com> wrote:

   How could I know that current iteration is the last in the series?
[1, 2, 3, 4, 5, 3, 4].each do |element|
   print element.to_s
   print ',' if !LAST
end

Try thread around
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/72518
for some sample implementations.

···

On Tue, Apr 03, 2007 at 12:00:09PM +0900, Mike wrote:

   How could I know that current iteration is the last in the series?
   For example:

[1, 2, 3, 4, 5, 3, 4].each do |element|
   print element.to_s
   print ',' if !LAST
end

Then *what* is your logic? What are you trying to achieve?

Kind regards

  robert

···

On 03.04.2007 04:56, Mike wrote:

   How could I know that current iteration is the last in the series?
   For example:

[1, 2, 3, 4, 5, 3, 4].each do |element|
   print element.to_s
   print ',' if !LAST
end

P.S. This is just an example. I don't want to use "join". My program
logic is much complicated than this example.

Phrogz wrote:

···

On Apr 2, 8:56 pm, "Mike" <michae...@gmail.com> wrote:

  How could I know that current iteration is the last in the series?
[1, 2, 3, 4, 5, 3, 4].each do |element|

ri each_with_index

You might also wanna restructure it as
   arr[0..-2].each(&blah); bloo[arr.last]
depending on the logic at hand.

Building off of Brian's suggestion in that thread, here
is a way to provide a 'countdown' as the end of the iteration
approaches. Default is to only flag the last item but you
can ask for any number of items to be flagged.

This is the first time I've found a need for the numeric return
value of nonzero?

module Enumerable
def each_with_countdown(count=0)
    queue = []
    each_with_index do |item,index|
      if index > (count)
       yield queue.shift, true
     end
     queue.push(item)
    end
    queue.each_with_index do |item, index|
      yield item, (count - index).nonzero?
    end
end

[1,2,3,4,5,6].each_with_countdown(3) { |item, more|
   case more
   when TrueClass
     puts "#{item}"
   when 3
     puts "#{item}, next to next to next to last item!"
   when 2
     puts "#{item}, next to next to last item!"
   when 1
     puts "#{item}, next to last item!"
   when NilClass
     puts "#{item}, last item"
   end
}

[1,2,3,4,5,6].each_with_countdown(1) { |item, more|
   puts "#{item}, more: #{more.inspect}"
}

[1].each_with_countdown { |item, more|
   puts "#{item}, more: #{more.inspect}"
}

StringIO.new("line1\nline2\nline3").each_with_countdown do |line, more|
   if more
     puts line
   else
     puts "last: #{line}"
   end
end

Gary Wright

···

On Apr 3, 2007, at 1:44 AM, Brian Candler wrote:

Try thread around
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/72518
for some sample implementations.

Interesting. Maybe it would be cleaner to return nil for all non-countdown
items, and then n-1, n-2 ... 0 as the flag (or n, n-1 ... 1). e.g.

require 'stringio'
module Enumerable
def each_with_countdown(count=1)
   queue = []
   each do |item|
     queue.push(item)
     yield queue.shift, nil if queue.size > count
   end
   queue.each_with_index do |item, index|
     yield item, count - index - 1
   end
end
end

[1,2,3,4,5,6].each_with_countdown(3) { |item, rem|
  case rem
  when nil
    puts "#{item}"
  when 2
    puts "#{item}, next to next to last item!"
  when 1
    puts "#{item}, next to last item!"
  when 0
    puts "#{item}, last item"
  end
}

[1,2,3,4,5,6].each_with_countdown(1) { |item, rem|
  puts "#{item}, rem: #{rem.inspect}"
}

[1].each_with_countdown { |item, rem|
  puts "#{item}, rem: #{rem.inspect}"
}

StringIO.new("line1\nline2\nline3").each_with_countdown do |line, rem|
  if rem
    puts "last: #{line}"
  else
    puts line
  end
end

···

On Tue, Apr 03, 2007 at 03:31:09PM +0900, Gary Wright wrote:

Building off of Brian's suggestion in that thread, here
is a way to provide a 'countdown' as the end of the iteration
approaches. Default is to only flag the last item but you
can ask for any number of items to be flagged.

I like this solution! Thank you.

···

On 4/3/07, Gary Wright <gwtmp01@mac.com> wrote:

On Apr 3, 2007, at 1:44 AM, Brian Candler wrote:
> Try thread around
> http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/72518
> for some sample implementations.

Building off of Brian's suggestion in that thread, here
is a way to provide a 'countdown' as the end of the iteration
approaches. Default is to only flag the last item but you
can ask for any number of items to be flagged.

This is the first time I've found a need for the numeric return
value of nonzero?

module Enumerable
def each_with_countdown(count=0)
    queue = []
    each_with_index do |item,index|
      if index > (count)
       yield queue.shift, true
     end
     queue.push(item)
    end
    queue.each_with_index do |item, index|
      yield item, (count - index).nonzero?
    end
end

[1,2,3,4,5,6].each_with_countdown(3) { |item, more|
   case more
   when TrueClass
     puts "#{item}"
   when 3
     puts "#{item}, next to next to next to last item!"
   when 2
     puts "#{item}, next to next to last item!"
   when 1
     puts "#{item}, next to last item!"
   when NilClass
     puts "#{item}, last item"
   end
}

[1,2,3,4,5,6].each_with_countdown(1) { |item, more|
   puts "#{item}, more: #{more.inspect}"
}

[1].each_with_countdown { |item, more|
   puts "#{item}, more: #{more.inspect}"
}

StringIO.new("line1\nline2\nline3").each_with_countdown do |line, more|
   if more
     puts line
   else
     puts "last: #{line}"
   end
end

Gary Wright

I liked the idea of the flag being true for all but the last item.
It just makes boolean expressions nicer for that special case even
when you are counting down.

···

On Apr 3, 2007, at 3:50 AM, Brian Candler wrote:

On Tue, Apr 03, 2007 at 03:31:09PM +0900, Gary Wright wrote:

Building off of Brian's suggestion in that thread, here
is a way to provide a 'countdown' as the end of the iteration
approaches. Default is to only flag the last item but you
can ask for any number of items to be flagged.

Interesting. Maybe it would be cleaner to return nil for all non-countdown
items, and then n-1, n-2 ... 0 as the flag (or n, n-1 ... 1). e.g.

No need for complex new code, this can be done with #inject very simply:

irb(main):005:0> print "back ", %w{aaa bbb ccc ddd}.inject {|x,y| print "front ", x, "\n"; y}, "\n"
front aaa
front bbb
front ccc
back ddd
=> nil

The trick is to use the form without arguments.

Kind regards

  robert

···

On 03.04.2007 10:24, Gary Wright wrote:

On Apr 3, 2007, at 3:50 AM, Brian Candler wrote:

On Tue, Apr 03, 2007 at 03:31:09PM +0900, Gary Wright wrote:

Building off of Brian's suggestion in that thread, here
is a way to provide a 'countdown' as the end of the iteration
approaches. Default is to only flag the last item but you
can ask for any number of items to be flagged.

Interesting. Maybe it would be cleaner to return nil for all non-countdown
items, and then n-1, n-2 ... 0 as the flag (or n, n-1 ... 1). e.g.

I liked the idea of the flag being true for all but the last item.
It just makes boolean expressions nicer for that special case even
when you are counting down.