Faster way to pick the every other array member?


#1

we have [1,2,3,4,5,6,7] and want [2,4,6]

Is there a way other than

fields=[1,2,3,4,5,6,7]
fields.collect!{|f|
f if fields.index(f)%2==1
}.compact!

And by another way I mean something shorter and more beautiful :).
Cheers,
V.-

http://www.braveworld.net/riva


#2

Hello

You can try the following:

fields = [“a”, “b”, “c”, “d”, “e”, “f”]
new_fields =[]
fields.each_index {|i| new_fields << fields[i] if i %2 == 0}

Cheers,
Christophe


#3

Christophe Poucet wrote:

Hello

You can try the following:

fields = [“a”, “b”, “c”, “d”, “e”, “f”]
new_fields =[]
fields.each_index {|i| new_fields << fields[i] if i %2 == 0}

Cheers,
Christophe

http://redhanded.hobix.com/inspect/hopscotchingArraysWithFlipFlops.html


#4

To be honest, I think that the hopscotching technique as well as:

f = true
fields = fields.select{f=!f}

are rather dirty hacks. They are short but they do not clearly convey
the meaning of the program.


#5

Christophe Poucet wrote:

To be honest, I think that the hopscotching technique as well as:

f = true
fields = fields.select{f=!f}

are rather dirty hacks. They are short but they do not clearly convey
the meaning of the program.

There’s probably dozens of ways to do it:

require ‘enumerator’
(1…10).each_slice(3) {|slc| p slc[0]}


#6

Damphyr wrote:

Cheers,
V.-

what about:

f = true
fields = fields.select{f=!f}

cheers

Simon


#7

Damphyr wrote:

we have [1,2,3,4,5,6,7] and want [2,4,6]

( A more general version of Simon’s:
f=true; p a.select{f=!f} ):

#--------
ix=-1; p a.select{ (ix+=1)%2==1 } #-> [2, 4, 6]
#--------

(Not pretty … not my fault)

I would prefer not having to maintain the index
in these situations. Something like this would
suit many similar needs:

p a.select{ _i_%2==1 }
  • where i (or whatever) is the index that Ruby
    is using internally.

daz


#8

Hi –

On Fri, 25 Nov 2005, Damphyr wrote:

we have [1,2,3,4,5,6,7] and want [2,4,6]

Is there a way other than

fields=[1,2,3,4,5,6,7]
fields.collect!{|f|
f if fields.index(f)%2==1
}.compact!

And by another way I mean something shorter and more beautiful :).

Here’s one possibility:

irb(main):016:0> a = [1,2,3,4,5,6,7]
=> [1, 2, 3, 4, 5, 6, 7]
irb(main):017:0> res = []
=> []
irb(main):018:0> (1…a.size).step(2) {|n| res << a[n] }
=> 1…7
irb(main):019:0> res
=> [2, 4, 6]

David


#9

Another one:

module Enumerable
def select_with_index
index = 0
select { |item|
res = yield item, index
index += 1
res
}
end
end

[1,2,3,4,5,6,7].select_with_index {|n, i| i % 2 == 1 }

I know this is basically the same, but you can see clearly what is
happening.


#10

On 11/25/05, Damphyr removed_email_address@domain.invalid wrote:

And by another way I mean something shorter and more beautiful :).

class Array

def skipper(interval=2,position=0)
(position…length).select { |i| i % interval == 0 }.map { |i|
self[i] }
end

end


#11

Damphyr wrote:

we have [1,2,3,4,5,6,7] and want [2,4,6]

Is there a way other than

fields=[1,2,3,4,5,6,7]
fields.collect!{|f|
f if fields.index(f)%2==1
}.compact!

fields.values_at( 1,3,5 )

or

fields.values_at( Array.new(fields.size/2){|i|i2+1} )


#12

Damphyr schrieb:

we have [1,2,3,4,5,6,7] and want [2,4,6]

Is there a way other than

fields=[1,2,3,4,5,6,7]
fields.collect!{|f|
f if fields.index(f)%2==1
}.compact!

And by another way I mean something shorter and more beautiful :).

fields.values_at(*(0…fields.size).select{|i|i%2==1})

Regards,
Pit


#13

res=[]; 1.step(a.size-1,2) {|n| res << a[n] }


#14

I’m kind of surprised that you don’t get an array of values back if you
call
Range#step(x) without a block.

That would make things much easier …

a.values_at( (2…6).step(2) )

… at least, that is what would make sense to me … anybody else?

j.

On 11/25/05, removed_email_address@domain.invalid removed_email_address@domain.invalid wrote:

res=[]; 1.step(a.size-1,2) {|n| res << a[n] }


“Remember. Understand. Believe. Yield! -> http://ruby-lang.org

Jeff W.


#15

Hi –

On Sat, 26 Nov 2005, Jeff W. wrote:

I’m kind of surprised that you don’t get an array of values back if you call
Range#step(x) without a block.

That would make things much easier …

a.values_at( (2…6).step(2) )

… at least, that is what would make sense to me … anybody else?

I can see your reasoning though I tend to come down on the side of not
liking iterators to create accumulator arrays unless you ask them to.
It’s kind of the same thing as the (much discussed) question of
whether a.zip(b) with a block should also return the zipped array (as
opposed to having the block be a way to avoid creating the whole
array).

David


#16

res=[]; 1.step(a.size-1,2) {|n| res << a[n] }


#17

On Sat, Nov 26, 2005 at 09:13:38AM +0900, Jeff W. wrote:

I’m kind of surprised that you don’t get an array of values back if you call
Range#step(x) without a block.

That would make things much easier …

a.values_at( (2…6).step(2) )

… at least, that is what would make sense to me … anybody else?

a = (0…20).to_a
a.values_at( *(2…6).step(2) ) # => [2, 4, 6]
RUBY_VERSION # => “1.9.0”


#18

Other than having to do the * that’s very cool.

It should be smart enought to figure out input param types …

or maybe add to the syntax for ranges ? ( 2…6 by 2 ) could be cool too

Anyways, thanks for the note about 1.9

j.

On 11/25/05, Mauricio Fernández <removed_email_address@domain.invalid > wrote:

… at least, that is what would make sense to me … anybody else?

a = (0…20).to_a
a.values_at( *(2…6).step(2) ) # => [2, 4, 6]
RUBY_VERSION # => “1.9.0”


Mauricio F.


"Remember. Understand. Believe. Yield! -> http://ruby-lang.org "

Jeff W.