问题
I was wondering if there is something similar to the Range but not with integers but with ordered couples (x, y). I am wondering if there is an easy way to do something like this:
((1,2)..(5,6)).each {|tmp| puts tmp} #=> (1,2) (3,4) (5,6)
EDIT: Maybe I was not 100% clear in my question :) I'll try to ask it in a different way.
If I had these couples: (3,4) and (5,6) I am looking for a way to help me generate:
(3,4), (4,5), (5,6)
if I had to exlpain it better : if the couples are (x,y)->
(x0,y0), ((x0+1),(y0+1)), ((x0+2), (y0+2)) and so on .
回答1:
You can use arrays as Range elements, such as:
> t = [1, 2]..[3, 4]
=> [1, 2]..[3, 4]
However, it cannot be iterated, because the Array
class lacks a succ
method.
> t.each {|tmp| puts tmp}
TypeError: can't iterate from Array
from (irb):5:in `each'
from (irb):5
from D:/Programmes/Ruby/bin/irb:12:in `<main>'
So if you want to allow iterating using arrays, define an Array#succ
method that does what you want:
class Array
def succ
self.map {|elem| elem + 1 }
end
end
which gives you:
> t = [1, 2]..[3, 4]
=> [1, 2]..[3, 4]
> t.each {|tmp| p tmp}
[1, 2]
[2, 3]
[3, 4]
=> [1, 2]..[3, 4]
回答2:
You can use Enumerable#each_slice
1.9.3-p327 :001 > (1..6).each_slice(2).to_a
=> [[1, 2], [3, 4], [5, 6]]
回答3:
Ruby is an object-oriented language. So, if you want to do something with an "ordered couple object", then you need … well … an OrderedCouple
object.
class OrderedCouple < Struct.new(:x, :y)
end
OrderedCouple.new(3, 4)
# => #<struct OrderedCouple x=3, y=4>
Uh, that looks ugly:
class OrderedCouple
def to_s; "(#{x}, #{y})" end
alias_method :inspect, :to_s
class << self; alias_method :[], :new end
end
OrderedCouple[3, 4]
# => (3, 4)
Range
s are used for two things: checking inclusion and iterating. In order for an object to be used as the start and end point of a Range
, it has to respond to <=>
. If you want to iterate over the Range
as well, then the start object has to respond to succ
:
class OrderedCouple
include Comparable
def <=>(other)
to_a <=> other.to_a
end
def to_a; [x, y] end
def succ
self.class[x.succ, y.succ]
end
end
puts *OrderedCouple[1, 2]..OrderedCouple[5, 6]
# (1, 2)
# (2, 3)
# (3, 4)
# (4, 5)
# (5, 6)
回答4:
Try this,
def tuples(x, y)
return enum_for(:tuples, x, y) unless block_given?
(0..Float::INFINITY).each { |i| yield [x + i, y + i] }
end
And then,
tuples(1,7).take(4)
# or
tuples(1,7).take_while { |x, y| x <= 3 && y <= 9 }
Both return
[[1, 7], [2, 8], [3, 9]]
来源:https://stackoverflow.com/questions/20608048/is-there-an-easy-way-to-generate-ordered-couples-in-ruby