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,
on 2009-07-02 14:21
on 2009-07-02 14:46
2009/7/2 Bil Kleb <Bil.Kleb@nasa.gov>: > > > 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"] Kind regards robert
on 2009-07-02 14:48
On Jul 2, 2009, at 7:45 AM, Robert Klemme wrote: >> then, >> and finally the 1.9 possibility, >> 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"] You need to reread what Bil was asking for. ;) James Edward Gray II
on 2009-07-02 14:52
On Jul 2, 2009, at 7:20 AM, Bil Kleb wrote: > 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 2009-07-02 14:55
Hi -- On Thu, 2 Jul 2009, Bil Kleb wrote: > > > 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 2009-07-02 16:38
2009/7/2 James Gray <james@grayproductions.net>:
> You need to reread what Bil was asking for. ;)
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
on 2009-07-02 20:35
David A. Black wrote: > 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] Nice.
on 2009-07-02 20:36
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,
on 2009-07-02 22:50
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. 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 2009-07-02 23:55
Robert Klemme wrote: > On 02.07.2009 20:33, Bil Kleb wrote: >> Ah, if it weren't for the two lines, I think I'd pick >> this one. > > Even with two lines I personally find it more elegant than some of the > solutions you posted. Mine we're solutions, just dreams. I liked David's solution the best because I dislike initialization separated from use (for some unknown-to-me reason). Regards,
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.