Iterating over an area in pairs.

  • Thread starter Thaddeus L Olczyk
  • Start date
T

Thaddeus L Olczyk

Is there a simple way to iterate over an array by taking any two pairs
( for this question I need one where I iterate over any two
combinations, but if someone can show how to do it by taking pairs so
that no two pairsa are duplicated that would be cool too ).
 
R

Robert Klemme

Thaddeus said:
Is there a simple way to iterate over an array by taking any two pairs
( for this question I need one where I iterate over any two
combinations, but if someone can show how to do it by taking pairs so
that no two pairsa are duplicated that would be cool too ).

1.8.4 doc states that there is a method each_slice that does what you
need, but my cygwin version doesn't seem to contain it:

robert@fussel ~
$ ruby -e '[1,2].each_slice(2){|*xx| p x}'
-e:1: undefined method `each_slice' for [1, 2]:Array (NoMethodError)

robert@fussel ~
$ ruby --version
ruby 1.8.4 (2005-12-24) [i386-cygwin]

You can work around in a number of ways, just an example

irb(main):004:0> a=[1,2,10,30]
=> [1, 2, 10, 30]
irb(main):005:0> 0.step(a.length-1, 2) {|i| puts a,a[i+1],"--"}
1
2
--
10
30
--
=> 0

Kind regards

robert
 
R

Ross Bamford

Thaddeus said:
Is there a simple way to iterate over an array by taking any two pairs
( for this question I need one where I iterate over any two
combinations, but if someone can show how to do it by taking pairs so
that no two pairsa are duplicated that would be cool too ).

1.8.4 doc states that there is a method each_slice that does what you
need, but my cygwin version doesn't seem to contain it:

robert@fussel ~
$ ruby -e '[1,2].each_slice(2){|*xx| p x}'
-e:1: undefined method `each_slice' for [1, 2]:Array (NoMethodError)

In 1.8 you need to require enumerator:

$ ruby -renumerator -e '[1,2,3,4].each_slice(2){|*x| p x}'
[[1, 2]]
[[3, 4]]

In 1.9 you're already set:

$ ruby9 -e '[1,2,3,4].each_slice(2){|*x| p x}'
[[1, 2]]
[[3, 4]]

Depending on what the OP wanted, each_cons might be useful, too:

$ ruby -renumerator -e '[1,2,3,4].each_cons(2){|*x| p x}'
[[1, 2]]
[[2, 3]]
[[3, 4]]
 
M

Martin DeMello

Thaddeus L Olczyk said:
Is there a simple way to iterate over an array by taking any two pairs
( for this question I need one where I iterate over any two
combinations, but if someone can show how to do it by taking pairs so
that no two pairsa are duplicated that would be cool too ).

Coincidentally, I wrote this yesterday (it's called Permutation because
I wanted to leave room to expand it into a generalised
permutation/combination library, but for now all I needed was the
combine method):

class Permutation
def initialize(n)
@array = n
end

def combine(k)
combinations(@array,k) {|i|
yield i
}
end

def combinations(ary, k)
if k == 1
ary.each {|i| yield }
return
end
if ary.length == k
yield ary
return
else
car, *cdr = ary
combinations(cdr, k-1) {|i| yield ([car] + i)}
combinations(cdr, k) {|i| yield i}
end
end
end

Use as:
a = Permutation.new(ary)
a.combine(2) {|i,j| }

martin
 
S

Sky Yin

A side question. I've noticed that:
=>[[1,2], [3,4]].each{|x,y| p x,y}
but:
=>[[1,2],[3,4]].each{|x| p x}

moreover:
=>[[1,2],[3,4]].each{|x,| p x}
I couldn't find the rule of such sub-array matching in doc. Is it a
special syntax?
 
R

Ross Bamford

A side question. I've noticed that:
=>[[1,2], [3,4]].each{|x,y| p x,y}
but:
=>[[1,2],[3,4]].each{|x| p x}

moreover:
=>[[1,2],[3,4]].each{|x,| p x}
I couldn't find the rule of such sub-array matching in doc. Is it a
special syntax?

Block arguments are handled using regular Ruby assignment rules, so
everything from *splat to nested assignment is supported. One place I
often find this useful is (contrived example):

[[:a,1],[:b,2],[:c,3]].inject({}) { |hsh,(sym, num)| hsh.merge!({ sym =>
num }) }
# => {:b=>2, :a=>1, :c=>3}

You'll find more in the Pickaxe, 2nd ed, p90-93 (or from the first edition
at http://www.rubycentral.com/book/tut_expressions.html - I doubt much has
changed in this regard.)

Hope that helps,
 
R

Robert Klemme

Ross Bamford said:
Block arguments are handled using regular Ruby assignment rules, so
everything from *splat to nested assignment is supported. One place I
often find this useful is (contrived example):

[[:a,1],[:b,2],[:c,3]].inject({}) { |hsh,(sym, num)| hsh.merge!({ sym
=> num }) }
# => {:b=>2, :a=>1, :c=>3}

I think I now why you use merge! but I'd prefer this one - a tad more
unelegant but also a tad more efficient:

[[:a,1],[:b,2],[:c,3]].inject({}) { |h,(k, v)| h[k]=v; h}
=> {:b=>2, :c=>3, :a=>1}

Kind regards

robert
 
R

Ross Bamford

Ross Bamford said:
Block arguments are handled using regular Ruby assignment rules, so
everything from *splat to nested assignment is supported. One place I
often find this useful is (contrived example):

[[:a,1],[:b,2],[:c,3]].inject({}) { |hsh,(sym, num)| hsh.merge!({ sym
=> num }) }
# => {:b=>2, :a=>1, :c=>3}

I think I now why you use merge! but I'd prefer this one - a tad more
unelegant but also a tad more efficient:

[[:a,1],[:b,2],[:c,3]].inject({}) { |h,(k, v)| h[k]=v; h}
=> {:b=>2, :c=>3, :a=>1}

Yeah, I started throwing merge! in there lately, mostly for that reason
but I guess it probably is quite inefficient really, especially as the
hash grows...

Thanks,
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top