Spliter of for...each: looping

when looping, using each, i find i am often wonton of a few nice
"sugers" myself.

  1. first iteration - do this first thing, but never again

  2. last iteration - do this last (same as else i think)

  3. not last iteration - do for every iteration BUT the last (this one
    would be very useful!!!

  4. not first - you get the idea

  5. an automatic index counter - i’m doing an arr.each but i also need a
    count too.

  6. and of course the few mentioned in the for…each…end thread
    concerning breaks or success (though i don’t find these as useful as the
    above)

but there’s no way in hell we can get all these things into blocks as we
know them today. perhaps there’s a new kind of looping contruct waiting
to be phathomed by us that can do all this (and more?)

~transmi

iterate x in arr
do

when _i == 1 # first

when _i == -1 # last

when _i != -1 # all but last

when _i != 1 # all but first

do

when _i == nil # if arr is empty? and perhaps nil? (else?)

ensure # on break and success?

end

_i is the automatic index (in this case _i started with 1, but probably
0 is better. of course its useable in the code,) notice the do’s, which
like the when’s, can go in any order. the loop is proccessed in order
dependent on the when conditions. do’s of course have no conditions. and
there’s no reason other conditions can’t be used based on other
variables.

did i miss anything? well you get the idea. what do you think?

could there be a block form?

arr.iterate { |x|

} _i == 1 {

} _i == -1 {

} _i != -1 {

} _1 != 1 {

} {

} _i == nil {

} …etc.?..

just some thoughts…

~transami

Hello –

···

On Thu, 11 Jul 2002, Tom Sawyer wrote:

  1. an automatic index counter - i’m doing an arr.each but i also need a
    count too.

Array#each_with_index will do the trick.

David


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

hmmm…

don’t really like the long name. alias iterate ?

but then i wonder, is it possible to define iterators that recognize
the number of parameters and act accordingly?

just the object

arr.each { |x|

}

the object with index

arr.each |x, i| {

}

~transami

···

On Wed, 2002-07-10 at 16:34, David Alan Black wrote:

Hello –

On Thu, 11 Jul 2002, Tom Sawyer wrote:

  1. an automatic index counter - i’m doing an arr.each but i also need a
    count too.

Array#each_with_index will do the trick.

David


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav


~transami

“They that can give up essential liberty to obtain a little
temporary safety deserve neither liberty nor safety.”
– Benjamin Franklin

oh, david, forgot to say: “good show old chap!”

···

On Wed, 2002-07-10 at 16:34, David Alan Black wrote:

Hello –

On Thu, 11 Jul 2002, Tom Sawyer wrote:

  1. an automatic index counter - i’m doing an arr.each but i also need a
    count too.

Array#each_with_index will do the trick.

David


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav


~transami

“They that can give up essential liberty to obtain a little
temporary safety deserve neither liberty nor safety.”
– Benjamin Franklin

Hi –

hmmm…

don’t really like the long name. alias iterate ?

I think it would be confusing not to see the familiar name.

but then i wonder, is it possible to define iterators that recognize
the number of parameters and act accordingly?

just the object

arr.each { |x|

}

the object with index

arr.each |x, i| {

}

Array#each can’t really work that way – there are too many possible
calls that need the two arguments:

[ [1,2], [3,4] ].each {|x,i| … } # etc.

but you could write an iterator that did (based on the block’s arity,
maybe). Then again, Enumerable gives you #each_with_index for free
:slight_smile:

David

···

On Thu, 11 Jul 2002, Tom Sawyer wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

david,

oh, my mistake, it all ready exists! yea!

only if it would match against -1 for last index though…oh well,
can’t have everything.

thanks a bunch. now i can stop making my own counters. how did i miss
that!?

~transami

···

On Wed, 2002-07-10 at 17:22, David Alan Black wrote:

Hi –

On Thu, 11 Jul 2002, Tom Sawyer wrote:

hmmm…

don’t really like the long name. alias iterate ?

I think it would be confusing not to see the familiar name.

but then i wonder, is it possible to define iterators that recognize
the number of parameters and act accordingly?

just the object

arr.each { |x|

}

the object with index

arr.each |x, i| {

}

Array#each can’t really work that way – there are too many possible
calls that need the two arguments:

[ [1,2], [3,4] ].each {|x,i| … } # etc.

but you could write an iterator that did (based on the block’s arity,
maybe). Then again, Enumerable gives you #each_with_index for free
:slight_smile:

David


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav


~transami

“They that can give up essential liberty to obtain a little
temporary safety deserve neither liberty nor safety.”
– Benjamin Franklin

Hi –

david,

oh, my mistake, it all ready exists! yea!

only if it would match against -1 for last index though…oh well,
can’t have everything.

Here’s a method with an even longer name :slight_smile: (by one character) which
gives the negative indices:

module Enumerable
def each_with_nindex
s = -1 - size
each {|e| yield e, s += 1}
end
end

%w{ a b c d e }.each_with_nindex do |e,i|
if i == -1
puts "Last element: #{e}"
end
end

=> Last element: e

David

···

On Thu, 11 Jul 2002, Tom Sawyer wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

each_with_nindex, rocking! i’ll throw that in my library, for sure.

it’s really nice for building strings with dividers, e.g. “a,b,c” in
order to keep that last comma from getting appended to the end.

thanks david!

···

On Wed, 2002-07-10 at 17:54, David Alan Black wrote:

Hi –

On Thu, 11 Jul 2002, Tom Sawyer wrote:

david,

oh, my mistake, it all ready exists! yea!

only if it would match against -1 for last index though…oh well,
can’t have everything.

Here’s a method with an even longer name :slight_smile: (by one character) which
gives the negative indices:

module Enumerable
def each_with_nindex
s = -1 - size
each {|e| yield e, s += 1}
end
end

%w{ a b c d e }.each_with_nindex do |e,i|
if i == -1
puts "Last element: #{e}"
end
end

=> Last element: e

David


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav


~transami

“They that can give up essential liberty to obtain a little
temporary safety deserve neither liberty nor safety.”
– Benjamin Franklin

Hi –

···

On Thu, 11 Jul 2002, Tom Sawyer wrote:

each_with_nindex, rocking! i’ll throw that in my library, for sure.

it’s really nice for building strings with dividers, e.g. “a,b,c” in
order to keep that last comma from getting appended to the end.

I like each_with_nindex too… but show me an example of this comma
problem that isn’t better solved with #join and I’ll put the price of
a beer in your Paypal account :slight_smile:

David


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

David Alan Black dblack@candle.superlink.net writes:

I like each_with_nindex too… but show me an example of this comma
problem that isn’t better solved with #join and I’ll put the price
of a beer in your Paypal account :slight_smile:

Heh, that’s what I was thinking – what about #join? :slight_smile:

%w(H A L).join(",")
=> “H,A,L”

···


Josh Huber

I like each_with_nindex too… but show me an example of this comma
problem that isn’t better solved with #join and I’ll put the price of
a beer in your Paypal account :slight_smile:

what i used to do:
q = ''
arr.each do |x|
q << ‘junk’ << x << ‘morejunk’ << ‘,‘
end
q.chomp!(’,’)

what i now do:
q = ''
arr.each_with_nindex do |x, n|
q << ‘junk’ << x << 'morejunk’
q << ‘,’ if n != -1
end

how do you do it with join?

note: how i used to do it is probably a tad faster actually

~transami

···

On Thu, 2002-07-11 at 04:55, David Alan Black wrote:

On Thu, 2002-07-11 at 04:55, David Alan Black wrote:

Hi –

On Thu, 11 Jul 2002, Tom Sawyer wrote:

each_with_nindex, rocking! i’ll throw that in my library, for sure.

it’s really nice for building strings with dividers, e.g. “a,b,c” in
order to keep that last comma from getting appended to the end.

I like each_with_nindex too… but show me an example of this comma
problem that isn’t better solved with #join and I’ll put the price of
a beer in your Paypal account :slight_smile:

David


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav


~transami

“They that can give up essential liberty to obtain a little
temporary safety deserve neither liberty nor safety.”
– Benjamin Franklin

q = ''
arr.each_with_nindex do |x, n|
  q << 'junk' << x << 'morejunk'
  q << ',' if n != -1
end

   arr.collect{|x| "junk#{x}morejunk" }.join(",")

Guy Decoux

Tom Sawyer transami@transami.net writes:

what i now do:
q = ''
arr.each_with_nindex do |x, n|
q << ‘junk’ << x << 'morejunk’
q << ‘,’ if n != -1
end

how do you do it with join?

note: how i used to do it is probably a tad faster actually

Hmm, how about something like…

arr.collect { |x| ‘junk’ + x + ‘morejunk’ }.join(",")

?

Seems a little cleaner/clearer, but that’s IMHO of course :slight_smile: Your
method is probably more efficient, since the one I mentioned creates
an intermediate array. I guess it depends on how performance critical
the code in question is.

···


Josh Huber

Hmm? What? Oh, never mind.

Hal

···

----- Original Message -----
From: “Josh Huber” huber@alum.wpi.edu
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Thursday, July 11, 2002 8:58 AM
Subject: Re: spliter of for…each: looping

David Alan Black dblack@candle.superlink.net writes:

I like each_with_nindex too… but show me an example of this comma
problem that isn’t better solved with #join and I’ll put the price
of a beer in your Paypal account :slight_smile:

Heh, that’s what I was thinking – what about #join? :slight_smile:

%w(H A L).join(",")
=> “H,A,L”

arr.collect{|x| “junk#{x}morejunk” }.join(",")

can you put conditionals in that?

q = ''
arr.each_with_nindex do |x, n|
q << ‘junk’ << x
q << ‘morejunk’ if x == 'more’
q << ‘,’ if n != -1
end

~transami

···

On Thu, 2002-07-11 at 09:23, ts wrote:

q = ''
arr.each_with_nindex do |x, n|
q << ‘junk’ << x << 'morejunk’
q << ‘,’ if n != -1
end

arr.collect{|x| “junk#{x}morejunk” }.join(",")

Guy Decoux


~transami

“They that can give up essential liberty to obtain a little
temporary safety deserve neither liberty nor safety.”
– Benjamin Franklin

“Hal E. Fulton” hal9000@hypermetrics.com writes:

Hmm? What? Oh, never mind.

=) Sorry about that!

···


Josh Huber

Seems a little cleaner/clearer, but that’s IMHO of course :slight_smile: Your
method is probably more efficient, since the one I mentioned creates
an intermediate array. I guess it depends on how performance critical
the code in question is.

actually joins faster. just tested it out. also discovered that:

“junk#{x}morejunk” is much faster then “junk” << x << “morejunk”

thanks for all the help guys! i think i can speed up miter a bit just by
using join.

~transmi

···

On Thu, 2002-07-11 at 09:50, Josh Huber wrote:

Tom Sawyer transami@transami.net writes:

what i now do:
q = ''
arr.each_with_nindex do |x, n|
q << ‘junk’ << x << 'morejunk’
q << ‘,’ if n != -1
end

how do you do it with join?

note: how i used to do it is probably a tad faster actually

Hmm, how about something like…

arr.collect { |x| ‘junk’ + x + ‘morejunk’ }.join(",")

?

Seems a little cleaner/clearer, but that’s IMHO of course :slight_smile: Your
method is probably more efficient, since the one I mentioned creates
an intermediate array. I guess it depends on how performance critical
the code in question is.


Josh Huber


~transami

“They that can give up essential liberty to obtain a little
temporary safety deserve neither liberty nor safety.”
– Benjamin Franklin

arr.collect{|x| "junk#{x}morejunk" }.join(",")

can you put conditionals in that?

Why not ?

You have a test in your block do...end, just do the same in #collect

Guy Decoux

Hi –

arr.collect{|x| “junk#{x}morejunk” }.join(",")

can you put conditionals in that?

q = ''
arr.each_with_nindex do |x, n|
q << ‘junk’ << x
q << ‘morejunk’ if x == 'more’
q << ‘,’ if n != -1
end

Sure:

arr.collect {|x| “junk#{x}#{‘more’ if x==‘more’}” }.join “,”

That’s in the nature of #collect (aka #map): you’re basically
translating from your original array to a new array of the same
length, using what happens in the block (one element at a time) as the
translator or transformer. And “what happens in the block” can
certainly be conditional on the value of the element(s).

By the way, another way to do the all-but-last thing with an array is:

arr[0…-2].each {|e| }

David

···

On Fri, 12 Jul 2002, Tom Sawyer wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

No worries, %[ J o s h ].join !

:slight_smile: Hal

···

----- Original Message -----
From: “Josh Huber” huber@alum.wpi.edu
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Thursday, July 11, 2002 2:03 PM
Subject: Re: spliter of for…each: looping

“Hal E. Fulton” hal9000@hypermetrics.com writes:

Hmm? What? Oh, never mind.

=) Sorry about that!