Is there an easy way to generate ordered couples in Ruby

江枫思渺然 提交于 2019-12-12 18:04:56

问题


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)

Ranges 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!