with :
array = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
I wrote :
array.index(array.detect {|x| x > 0}) => 15
is there a better and simpler way to do it ?
thanks
joss
with :
array = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
I wrote :
array.index(array.detect {|x| x > 0}) => 15
is there a better and simpler way to do it ?
thanks
joss
In that case, it is simpler to use an external counter, i think :
c = 0
array.each{|v| break if not v.zero?; c += 1}
puts c # => 15
Le dimanche 26 novembre 2006 15:00, Josselin a écrit :
with :
array = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0]I wrote :
array.index(array.detect {|x| x > 0}) => 15is there a better and simpler way to do it ?
thanksjoss
Hi,
From: Josselin <josselin@wanadoo.fr>
Reply-To: ruby-talk@ruby-lang.org
To: ruby-talk@ruby-lang.org (ruby-talk ML)
Subject: find index of first non zeo value in array
Date: Sun, 26 Nov 2006 23:00:10 +0900with :
array = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]I wrote :
array.index(array.detect {|x| x > 0}) => 15is there a better and simpler way to do it ?
thanksjoss
How about this:
array.index((array-[0])[0])
Regards,
Park Heesob
_________________________________________________________________
Don't just search. Find. Check out the new MSN Search! http://search.msn.com/
Did we have a solution with #inject already? In case we didn't:
irb(main):001:0> require 'enumerator'
=> true
irb(main):002:0> a=Array.new(10,0) << 666 << 0
=> [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 666, 0]
irb(main):003:0> a.to_enum(:each_with_index).inject(nil) {|pp,(x,i)| break i unless x == 0}
=> 10
irb(main):004:0> a[0..5]
=> [0, 0, 0, 0, 0, 0]
irb(main):005:0> a[0..5].to_enum(:each_with_index).inject(nil) {|pp,(x,i)| break i unless x == 0}
=> nil
Kind regards
robert
On 26.11.2006 14:59, Josselin wrote:
with :
array = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]I wrote :
array.index(array.detect {|x| x > 0}) => 15is there a better and simpler way to do it ?
thanks
# uber_nasty_for_laughs.rb
array.to_s.split(/[1-9]/)[0].length
On 11/26/06, Josselin <josselin@wanadoo.fr> wrote:
with :
array = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0]I wrote :
array.index(array.detect {|x| x > 0}) => 15is there a better and simpler way to do it ?
thanksjoss
Hi --
On Sun, 26 Nov 2006, Olivier wrote:
Le dimanche 26 novembre 2006 15:00, Josselin a écrit :
with :
array = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0]I wrote :
array.index(array.detect {|x| x > 0}) => 15is there a better and simpler way to do it ?
thanksjoss
In that case, it is simpler to use an external counter, i think :
c = 0
array.each{|v| break if not v.zero?; c += 1}
puts c # => 15
Or:
c = array.each_with_index {|e,i| break i unless e.zero? }
David
--
David A. Black | dblack@wobblini.net
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org
with :
array = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0]I wrote :
array.index(array.detect {|x| x > 0}) => 15is there a better and simpler way to do it ?
thanksjoss
In that case, it is simpler to use an external counter, i think :
c = 0
array.each{|v| break if not v.zero?; c += 1}
puts c # => 15
You can ask Ruby to maintain the counter, if you want:
>> require "enumerator"
=> true
>> array = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0,
?> 0, 0, 0, 0, 0, 0]
=> [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
>> result = array.enum_with_index.find { |n, i| n.nonzero? }.last rescue nil
=> 15
>> array.slice!(15, 1)
=> [21]
>> array
=> [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
>> result = array.enum_with_index.find { |n, i| n.nonzero? }.last rescue nil
=> nil
James Edward Gray II
On Nov 26, 2006, at 8:54 AM, Olivier wrote:
Le dimanche 26 novembre 2006 15:00, Josselin a écrit :
Robert Klemme wrote:
Did we have a solution with #inject already? In case we didn't:
irb(main):001:0> require 'enumerator'
=> true
irb(main):002:0> a=Array.new(10,0) << 666 << 0
=> [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 666, 0]
irb(main):003:0> a.to_enum(:each_with_index).inject(nil) {|pp,(x,i)| break i unless x == 0}
=> 10
sub 'inject(nil) {|pp,(x,i)|', 'find {|x,i|'
But I vote for adding to Enumerable or Array. #index_where or #find_by or something. (My preference over alias-and-delegate.)
Devin
Not a generic way, but pretty good for this specific problem.
Regards,
Pradeep
On Sunday 26 November 2006 21:22, Park Heesob wrote:
Hi,
>From: Josselin <josselin@wanadoo.fr>
>Reply-To: ruby-talk@ruby-lang.org
>To: ruby-talk@ruby-lang.org (ruby-talk ML)
>Subject: find index of first non zeo value in array
>Date: Sun, 26 Nov 2006 23:00:10 +0900
>
>with :
>array = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0,
> 0, 0, 0, 0, 0]
>
>I wrote :
>array.index(array.detect {|x| x > 0}) => 15
>
>is there a better and simpler way to do it ?
>thanks
>
>jossHow about this:
array.index((array-[0])[0])
Regards,
Park Heesob
_________________________________________________________________
Don't just search. Find. Check out the new MSN Search!
http://search.msn.com/
Robert Klemme wrote:
On 26.11.2006 14:59, Josselin wrote:
> with :
> array = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0,
> 0, 0, 0, 0, 0]
>
> I wrote :
> array.index(array.detect {|x| x > 0}) => 15
>
> is there a better and simpler way to do it ?
> thanksDid we have a solution with #inject already?
array.inject(0){|i,e| if e>0; break i else i+1 end}
No, I'm wrong; that leaves c == a if there's no non-zero element.
Ignore.
David
On Mon, 27 Nov 2006, dblack@wobblini.net wrote:
Or:
c = array.each_with_index {|e,i| break i unless e.zero? }
--
David A. Black | dblack@wobblini.net
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org
Hi --
On Mon, 27 Nov 2006, James Edward Gray II wrote:
On Nov 26, 2006, at 8:54 AM, Olivier wrote:
Le dimanche 26 novembre 2006 15:00, Josselin a écrit :
array.index(array.detect {|x| x > 0}) => 15
c = 0
array.each{|v| break if not v.zero?; c += 1}
puts c # => 15result = array.enum_with_index.find { |n, i| n.nonzero? }.last rescue nil
That seems kind of like a reinvention of Array#index, though. It also
has the usual problem with rescue, i.e., that you might rescue the
wrong thing (if nonzero? is mistyped or whatever). Do you see an
advantage to doing it this way, rather than the index/detect way?
(I'm being lazy and not benchmarking them....)
David
--
David A. Black | dblack@wobblini.net
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org
William James wrote:
Robert Klemme wrote:
> > with :
> > array = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0,
> > 0, 0, 0, 0, 0]
> >
> > I wrote :
> > array.index(array.detect {|x| x > 0}) => 15
> >
> > is there a better and simpler way to do it ?
> > thanks
>
> Did we have a solution with #inject already?array.inject(0){|i,e| if e>0; break i else i+1 end}
array.inject(0){|i,e| break i if e>0; i+1 }
> On 26.11.2006 14:59, Josselin wrote:
Well, it only walks the Array once. The other way walks it once for detect() and again for index(). I agree that it's not sexy code though.
I believe there has been talk in the past of having index() take a block for matching. That would solve this problem ideally. I can submit an RCR if people think it's worth it, but I'm pretty sure Matz said it was OK last time it came up... (Correct me if I am wrong!)
James Edward Gray II
On Nov 26, 2006, at 9:53 AM, dblack@wobblini.net wrote:
On Mon, 27 Nov 2006, James Edward Gray II wrote:
On Nov 26, 2006, at 8:54 AM, Olivier wrote:
Le dimanche 26 novembre 2006 15:00, Josselin a écrit :
array.index(array.detect {|x| x > 0}) => 15
c = 0
array.each{|v| break if not v.zero?; c += 1}
puts c # => 15result = array.enum_with_index.find { |n, i| n.nonzero? }.last rescue nil
That seems kind of like a reinvention of Array#index, though. It also
has the usual problem with rescue, i.e., that you might rescue the
wrong thing (if nonzero? is mistyped or whatever). Do you see an
advantage to doing it this way, rather than the index/detect way?
(I'm being lazy and not benchmarking them....)
Using a regular expression ...
array.join =~ /[^0]/
The inject method is faster, though, because you do not have to create
a string. I'm assuming that the "array.index((array-[0])[0])" solution
suffers from the same problem -- creating another object under the
covers ...
$ ruby tmp.rb
user system total real
inject 2.874000 0.000000 2.874000 ( 2.884000)
index 0.721000 0.000000 0.721000 ( 0.731000)
regexp 3.755000 0.000000 3.755000 ( 3.765000)
Wow! Looks like the "index" method wins hands down.
But mine is still shorter
TwP
On 11/27/06, William James <w_a_x_man@yahoo.com> wrote:
William James wrote:
> Robert Klemme wrote:
> > On 26.11.2006 14:59, Josselin wrote:
> > > with :
> > > array = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0,
> > > 0, 0, 0, 0, 0]
> > >
> > > I wrote :
> > > array.index(array.detect {|x| x > 0}) => 15
> > >
> > > is there a better and simpler way to do it ?
> > > thanks
> >
> > Did we have a solution with #inject already?
>
> array.inject(0){|i,e| if e>0; break i else i+1 end}array.inject(0){|i,e| break i if e>0; i+1 }
Hi --
array.index(array.detect {|x| x > 0}) => 15
c = 0
array.each{|v| break if not v.zero?; c += 1}
puts c # => 15result = array.enum_with_index.find { |n, i| n.nonzero? }.last rescue nil
That seems kind of like a reinvention of Array#index, though. It also
has the usual problem with rescue, i.e., that you might rescue the
wrong thing (if nonzero? is mistyped or whatever). Do you see an
advantage to doing it this way, rather than the index/detect way?
(I'm being lazy and not benchmarking them....)Well, it only walks the Array once. The other way walks it once for detect() and again for index(). I agree that it's not sexy code though.
I believe there has been talk in the past of having index() take a block for matching. That would solve this problem ideally. I can submit an RCR if people think it's worth it, but I'm pretty sure Matz said it was OK last time it came up... (Correct me if I am wrong!)
Yes, there's an accepted RCR for it. That will be good.
This exchange relates to something I've been pondering for a while,
namely: is there always (or very, very often) an inverse relation
between elegance of code and efficiency? I don't mean to sound like
I'm singling out your example -- on the contrary, it seems that over
and over we see cases where a nice concise solution bombs out compared
to one that's longer, possibly less clear (I still can't read the
enum* stuff as quickly and confidently as I can read the regular
Enumerable stuff, though that may just be due to stupidity), but
faster.
I haven't really documented or studied this in detail, though it does
seem to keep happening. It might be interesting to look into further.
David
On Mon, 27 Nov 2006, James Edward Gray II wrote:
On Nov 26, 2006, at 9:53 AM, dblack@wobblini.net wrote:
On Mon, 27 Nov 2006, James Edward Gray II wrote:
On Nov 26, 2006, at 8:54 AM, Olivier wrote:
Le dimanche 26 novembre 2006 15:00, Josselin a écrit :
--
David A. Black | dblack@wobblini.net
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org
James Edward Gray II wrote:
I believe there has been talk in the past of having index() take a block for matching.
Meh... talk schmalk...
class Array
alias orig_index index
def index(*args)
return orig_index(*args) unless block_given?
(0...length).each do |i|
return i if yield self[i]
end
nil
end
end
array = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
array.index 21 #=> 15
array.index {|n| n.nonzero? } #=> 15
Devin
IIRC Matz accepted it straight into 1.9. It's implemented there now:
$ ruby9 -ve 'p [0,0,0,15,0].index { |e| e > 0 }'
ruby 1.9.0 (2006-11-26 patchlevel 0) [i686-linux]
3
On Mon, 2006-11-27 at 01:00 +0900, James Edward Gray II wrote:
I believe there has been talk in the past of having index() take a
block for matching. That would solve this problem ideally. I can
submit an RCR if people think it's worth it, but I'm pretty sure Matz
said it was OK last time it came up... (Correct me if I am wrong!)
--
Ross Bamford - rosco@roscopeco.REMOVE.co.uk
Just saw this..
@ ruby conf, there were talks about the speed of ruby's regex
Being that ruby was the first language I picked up, I'm curious as to
how other languages(such as perl) compare from a performance
standpoint with your examples.
I'm not expecting perl to be slower an any scenerio, but is the perl
index() quicker or slower than a perl regex? If the latter, is the
performance ratio proportional to that of our ruby examples?
On 11/27/06, Tim Pease <tim.pease@gmail.com> wrote:
On 11/27/06, William James <w_a_x_man@yahoo.com> wrote:
>
> William James wrote:
> > Robert Klemme wrote:
> > > On 26.11.2006 14:59, Josselin wrote:
> > > > with :
> > > > array = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0,
> > > > 0, 0, 0, 0, 0]
> > > >
> > > > I wrote :
> > > > array.index(array.detect {|x| x > 0}) => 15
> > > >
> > > > is there a better and simpler way to do it ?
> > > > thanks
> > >
> > > Did we have a solution with #inject already?
> >
> > array.inject(0){|i,e| if e>0; break i else i+1 end}
>
> array.inject(0){|i,e| break i if e>0; i+1 }
>Using a regular expression ...
array.join =~ /[^0]/
The inject method is faster, though, because you do not have to create
a string. I'm assuming that the "array.index((array-[0])[0])" solution
suffers from the same problem -- creating another object under the
covers ...$ ruby tmp.rb
user system total real
inject 2.874000 0.000000 2.874000 ( 2.884000)
index 0.721000 0.000000 0.721000 ( 0.731000)
regexp 3.755000 0.000000 3.755000 ( 3.765000)Wow! Looks like the "index" method wins hands down.
But mine is still shorter
TwP
Seems to be a general symptom of everything being optimised to run C
code - the C-like solutions win out.
m.
On 11/26/06, dblack@wobblini.net <dblack@wobblini.net> wrote:
This exchange relates to something I've been pondering for a while,
namely: is there always (or very, very often) an inverse relation
between elegance of code and efficiency? I don't mean to sound like
I'm singling out your example -- on the contrary, it seems that over
and over we see cases where a nice concise solution bombs out compared
to one that's longer, possibly less clear (I still can't read the
enum* stuff as quickly and confidently as I can read the regular
Enumerable stuff, though that may just be due to stupidity), but
faster.