delete_if_with_index or delete_at(array) in 1.8.6?

B

Bil Kleb

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,
 
R

Robert Klemme

2009/7/2 Bil Kleb said:
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,

=A0array.delete_if_with_index{ |e,i| e < i }

then,

=A0remove_indices =3D []
=A0array.each_with_index{ |e,i| remove_indices << i if e < i }
=A0array.delete_at( remove_indices )

or the same, but with a fictious inject_with_index,

=A0remove_indices =3D inject_with_index([]){|acc,e,i| acc << i if e < i }
=A0array.delete_at( remove_indices )

and finally the 1.9 possibility,

=A0array.map_with_index!{ |e,i| e < i ? nil : e }.compact!

before compromising with

=A0array =3D (0...array.size).zip(array).map{ |i,e| e < i ? nil : e }.com= pact

Anything more elegant available?

Or perhaps an alternative way to attack the problem?

irb(main):010:0> a =3D %w{foo bar baz}
=3D> ["foo", "bar", "baz"]
irb(main):011:0> current =3D 1
=3D> 1
irb(main):012:0> a.slice! 0...current
=3D> ["foo"]
irb(main):013:0> a
=3D> ["bar", "baz"]

Kind regards

robert


--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 
J

James Gray

2009/7/2 Bil Kleb said:
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"]

You need to reread what Bil was asking for. ;)

James Edward Gray II
 
J

James Gray

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?
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
 
D

David A. Black

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 })

=> [0, 1, 2, 4, 6, 7]

or some variant thereof.


David

--
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
 
R

Robert Klemme

2009/7/2 James Gray said:
You need to reread what Bil was asking for. =A0;)

Right. Now I got it. He means something like

irb(main):001:0> a =3D (1..10).map { rand(10) }
=3D> [8, 0, 4, 2, 1, 4, 5, 4, 2, 9]
irb(main):002:0> i =3D -1
=3D> -1
irb(main):003:0> a.delete_if {|x| i +=3D 1; x < i}
=3D> [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

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 
B

Bil Kleb

Robert said:
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,
 
R

Robert Klemme

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
 
B

Bil Kleb

Robert said:
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,
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top