Hi,
Given an array of integers, I need to delete all those
entries that are lower than the current array index.
I first thought of the non-existent,
array.delete_if_with_index{ |e,i| e < i }
then,
remove_indices = []
array.each_with_index{ |e,i| remove_indices << i if e < i }
array.delete_at( remove_indices )
or the same, but with a fictious inject_with_index,
remove_indices = inject_with_index([]){|acc,e,i| acc << i if e < i }
array.delete_at( remove_indices )
and finally the 1.9 possibility,
array.map_with_index!{ |e,i| e < i ? nil : e }.compact!
before compromising with
array = (0...array.size).zip(array).map{ |i,e| e < i ? nil : e }.compact
Anything more elegant available?
Or perhaps an alternative way to attack the problem?
Thanks,
···
--
http://twitter.com/bil_kleb
http://fun3d.larc.nasa.gov
irb(main):010:0> a = %w{foo bar baz}
=> ["foo", "bar", "baz"]
irb(main):011:0> current = 1
=> 1
irb(main):012:0> a.slice! 0...current
=> ["foo"]
irb(main):013:0> a
=> ["bar", "baz"]
Kind regards
robert
···
2009/7/2 Bil Kleb <Bil.Kleb@nasa.gov>:
Hi,
Given an array of integers, I need to delete all those
entries that are lower than the current array index.
I first thought of the non-existent,
array.delete_if_with_index{ |e,i| e < i }
then,
remove_indices =
array.each_with_index{ |e,i| remove_indices << i if e < i }
array.delete_at( remove_indices )
or the same, but with a fictious inject_with_index,
remove_indices = inject_with_index(){|acc,e,i| acc << i if e < i }
array.delete_at( remove_indices )
and finally the 1.9 possibility,
array.map_with_index!{ |e,i| e < i ? nil : e }.compact!
before compromising with
array = (0...array.size).zip(array).map{ |i,e| e < i ? nil : e }.compact
Anything more elegant available?
Or perhaps an alternative way to attack the problem?
--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
Given an array of integers, I need to delete all those
entries that are lower than the current array index.
Anything more elegant available?
Or perhaps an alternative way to attack the problem?
On Ruby 1.9, your very first example can almost be made to work as is:
>> a = Array.new(10) { |i| i + [-1, 0, 1][rand(3)] }
=> [-1, 1, 2, 4, 3, 5, 7, 7, 9, 10]
>> a.delete_if.with_index { |e, i| e < i }
=> [1, 2, 4, 5, 7, 7, 9, 10]
James Edward Gray II
···
On Jul 2, 2009, at 7:20 AM, Bil Kleb wrote:
Hi --
Hi,
Given an array of integers, I need to delete all those
entries that are lower than the current array index.
I first thought of the non-existent,
array.delete_if_with_index{ |e,i| e < i }
then,
remove_indices =
array.each_with_index{ |e,i| remove_indices << i if e < i }
array.delete_at( remove_indices )
or the same, but with a fictious inject_with_index,
remove_indices = inject_with_index(){|acc,e,i| acc << i if e < i }
array.delete_at( remove_indices )
and finally the 1.9 possibility,
array.map_with_index!{ |e,i| e < i ? nil : e }.compact!
before compromising with
array = (0...array.size).zip(array).map{ |i,e| e < i ? nil : e }.compact
Anything more elegant available?
Or perhaps an alternative way to attack the problem?
In 1.9 I would do:
a = [0,1,2,1,4,3,6,7,2]
=> [0, 1, 2, 1, 4, 3, 6, 7, 2]
a.reject!.with_index {|e,i| e < i }
=> [0, 1, 2, 4, 6, 7]
In 1.8 I'm not coming up with anything more elegant than:
a.values_at(*(0...a.size).reject {|i| a[i] < i })
=> [0, 1, 2, 4, 6, 7]
or some variant thereof.
David
···
On Thu, 2 Jul 2009, Bil Kleb wrote:
--
David A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.rubypal.com
Now available: The Well-Grounded Rubyist (http://manning.com/black2\)
"Ruby 1.9: What You Need To Know" Envycasts with David A. Black
http://www.envycasts.com
You need to reread what Bil was asking for. 
James Edward Gray II
···
On Jul 2, 2009, at 7:45 AM, Robert Klemme wrote:
2009/7/2 Bil Kleb <Bil.Kleb@nasa.gov>:
Hi,
Given an array of integers, I need to delete all those
entries that are lower than the current array index.
I first thought of the non-existent,
array.delete_if_with_index{ |e,i| e < i }
then,
remove_indices =
array.each_with_index{ |e,i| remove_indices << i if e < i }
array.delete_at( remove_indices )
or the same, but with a fictious inject_with_index,
remove_indices = inject_with_index(){|acc,e,i| acc << i if e < i }
array.delete_at( remove_indices )
and finally the 1.9 possibility,
array.map_with_index!{ |e,i| e < i ? nil : e }.compact!
before compromising with
array = (0...array.size).zip(array).map{ |i,e| e < i ? nil : e }.compact
Anything more elegant available?
Or perhaps an alternative way to attack the problem?
irb(main):010:0> a = %w{foo bar baz}
=> ["foo", "bar", "baz"]
irb(main):011:0> current = 1
=> 1
irb(main):012:0> a.slice! 0...current
=> ["foo"]
irb(main):013:0> a
=> ["bar", "baz"]
Right. Now I got it. He means something like
irb(main):001:0> a = (1..10).map { rand(10) }
=> [8, 0, 4, 2, 1, 4, 5, 4, 2, 9]
irb(main):002:0> i = -1
=> -1
irb(main):003:0> a.delete_if {|x| i += 1; x < i}
=> [8, 4, 9]
irb(main):004:0>
Correct? Thanks for the heads up, James!
Site note: there seems to be a certain setting of the mind which
prevents that we consider a mutating operation in a "read only" block
used as filtering criterion. Yet we can do it. It took me a while,
too. 
Kind regards
robert
···
2009/7/2 James Gray <james@grayproductions.net>:
You need to reread what Bil was asking for. 
--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
Robert Klemme wrote:
irb(main):002:0> i = -1
irb(main):003:0> a.delete_if {|x| i += 1; x < i}
Ah, if it weren't for the two lines, I think I'd pick
this one.
Regards,
···
--
http://twitter.com/bil_kleb
Even with two lines I personally find it more elegant than some of the solutions you posted. I can even give you reasons:
- it is straightforward and thus easy to understand
- little code, despite the two lines
- it does not create any temporary arrays of indexes or such which is the reason for:
- it is probably pretty efficient
- oh, and it should work on all versions of Ruby

Kind regards
robert
···
On 02.07.2009 20:33, Bil Kleb wrote:
Robert Klemme wrote:
irb(main):002:0> i = -1
irb(main):003:0> a.delete_if {|x| i += 1; x < i}
Ah, if it weren't for the two lines, I think I'd pick
this one.
--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/