在 Ruby 中使用元组?

有人在 Ruby 中使用元组吗?如果是这样,如何实现元组?Ruby 散列很好,而且几乎也可以工作,但是我真的希望看到类似 Python 中的 Tuple 类的东西,在这里您可以使用 .表示法来查找您正在查找的值。我希望这样做,以便能够创建 D的实现,类似于 Python 的 迪伊

102436 次浏览

OpenStruct?

Brief example:

require 'ostruct'


person = OpenStruct.new
person.name    = "John Smith"
person.age     = 70
person.pension = 300


puts person.name     # -> "John Smith"
puts person.age      # -> 70
puts person.address  # -> nil

Based on the fact that you talk about hashes and . notation I'm going to assume you mean a different kind of tuple than the (1. "a") sort. You're probably looking for the Struct class. eg:

Person = Struct.new(:name, :age)
me = Person.new
me.name = "Guy"
me.age =  30

While this isn't strictly a tuple (can't do dot notation of members), you can assign a list of variables from a list, which often will solve issues with ruby being pass-by-value when you are after a list of return values.

E.g.

:linenum > (a,b,c) = [1,2,3]
:linenum > a
=> 1
:linenum > b
=> 2
:linenum > c
=> 3

You can do something similiar with destructuring:

def something((a, b))
a + b
end


p something([1, 2])

This prints out 3 as expected.

I'm the author of Gem for Ruby tuples.

You are provided with two classes:

  • Tuple in general
  • Pair in particular

You can initialize them in different ways:

Tuple.new(1, 2)
Tuple.new([1, 2])
Tuple(1, 2)
Tuple([1, 2])
Tuple[1, 2]

Both of the classes have some auxiliary methods:

  • length / arity - which returns number of values inside tuple
  • first / last / second (only pair) - which returns a corresponding elements
  • [] that gives you an access to a particular elements

You can mock the Scala tuples with this trick :

Tuple = Struct.new(:_1, :_2)


2.2.5 :003 > t = Tuple.new("a", "b")
=> #<struct Tuple _1="a", _2="b">
2.2.5 :004 > t._1
=> "a"
2.2.5 :005 > t._2
=> "b"

but here you can't have destructuring:

2.2.5 :012 > a, b = t
=> {:_1=>"a", :_2=>"b"}
2.2.5 :013 > a
=> {:_1=>"a", :_2=>"b"}
2.2.5 :014 > b
=> nil

But thanks to this trick : https://gist.github.com/stevecj/9ace6a70370f6d1a1511 destructuring will work:

2.2.5 :001 > Tuple = Struct.new(:_1, :_2)
=> Tuple
2.2.5 :002 > t = Tuple.new("a", "b")
=> #<struct Tuple _1="a", _2="b">
2.2.5 :003 > t._1
=> "a"
2.2.5 :004 > class Tuple ; def to_ary ; to_a ; end ; end
=> :to_ary
2.2.5 :005 > a, b = t
=> #<struct Tuple _1="a", _2="b">
2.2.5 :006 > a
=> "a"
2.2.5 :007 > b
=> "b"

Arrays are cool to use as tuples because of destructuring

a = [[1,2], [2,3], [3,4]]
a.map {|a,b| a+b }

Struct give you convenient . accessors

Person = Struct.new(:first_name, :last_name)
ppl = Person.new('John', 'Connor')
ppl.first_name
ppl.last_name

You can get the convenience of both worlds with to_ary

Person = Struct.new(:first_name, :last_name) do
def to_ary
[first_name, last_name]
end
end
# =>
[
Person.new('John', 'Connor'),
Person.new('John', 'Conway')
].map { |a, b| a + ' ' + b  }
# => ["John Connor", "John Conway"]