Bil_K
July 2, 2009, 2:21pm
1
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,
Bil_K
July 2, 2009, 2:46pm
2
2009/7/2 Bil K. [email protected] :
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
Bil_K
July 2, 2009, 2:48pm
3
On Jul 2, 2009, at 7:45 AM, Robert K. 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 G. II
Bil_K
July 2, 2009, 2:52pm
4
On Jul 2, 2009, at 7:20 AM, Bil K. 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 G. II
Bil_K
July 2, 2009, 2:55pm
5
Hi –
On Thu, 2 Jul 2009, Bil K. 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
Bil_K
July 2, 2009, 4:38pm
6
2009/7/2 James G. [email protected] :
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
Bil_K
July 2, 2009, 8:36pm
7
Robert K. 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,
Bil_K
July 2, 2009, 11:55pm
9
Robert K. wrote:
On 02.07.2009 20:33, Bil K. 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,
Bil_K
July 2, 2009, 10:50pm
10
On 02.07.2009 20:33, Bil K. wrote:
Robert K. 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