2011-11-10 63 views
15

Có một lý do hợp lệ để không có phương thức trả về dữ liệu của cấu trúc chuẩn ruby ​​dưới dạng băm (thành viên, cặp giá trị) không? Thấy rằng cấu trúc và băm có trường hợp sử dụng rất giống nhau, tôi ngạc nhiên rằng không có phương pháp như vậy tồn tại. Hay là thế, và tôi quá mù? Thật dễ dàng để thực hiện (và tôi đã làm như vậy bây giờ), nhưng thiếu chức năng như vậy trong libs tiêu chuẩn, có tôi nghĩ rằng tôi có thể đã không thực sự nắm bắt được khái niệm về cấu trúc trong ruby.trả về dữ liệu cấu trúc dưới dạng băm trong ruby ​​

Trả lời

30

(của Ruby < = 1.9.3) OpenStructOpenStruct#marshall_dumpStructStruct#each_pair (sử dụng to_a để nhận các cặp và Hash + to_a để nhận hàm băm):

Person = Struct.new(:name, :age) 
person = Person.new("Jamie", 23) 
person_hash = Hash[person.each_pair.to_a] 
#=> {:age=>23, :name=>"Jamie"} 

Với Ruby điều 2.0 là dễ dàng hơn: Struct#to_h, OpenStruct#to_h:

Person = Struct.new(:name, :age) 
person = Person.new("Jamie", 23) 
person_hash = person.to_h 
#=> {:age=>23, :name=>"Jamie"} 
+0

Cảm ơn vì giải pháp 'tiêm chích' này, và quan trọng hơn đối với người Informatian là OpenStruct có một phương pháp như vậy, ở một mức độ, trả lời câu hỏi của tôi đây là một điều khả thi để hỏi về một ruby ​​Struct (rõ ràng là nó). – cvshepherd

+4

Trong Ruby 2.0 có một phương thức to_h trong Struct. –

4

Tôi không nghĩ rằng các trường hợp sử dụng cho băm và cấu trúc rất giống nhau. Một băm cho phép bạn lưu trữ một số lượng các cặp khóa-giá trị thay đổi và phù hợp để lưu trữ hàng nghìn cặp nếu bạn muốn. Không có khóa cụ thể nào được đảm bảo có mặt. Với Struct, bạn luôn biết bộ "phím" sẽ là gì và nó thường nhỏ (dưới 20).

Có thể sử dụng dấu gạch ngang để liên kết một số thông tin với một số lượng lớn các đối tượng khác nhau. Các dấu gạch ngang được sử dụng để chỉ định tham số tùy chọn cho hàm. Structs có thể được sử dụng khi bạn muốn giữ một số thông tin được xác định rõ ràng với nhau trong một đối tượng.

Tôi chưa bao giờ muốn chuyển đổi từ cấu trúc thành băm nên tôi tự hỏi tại sao bạn làm như vậy.

CHỈNH SỬA 1: Bạn có biết bạn có thể sử dụng cú pháp không bẻ khóa này với Structs không?

P = Struct.new(:x,:y) 
p = P.new(1,2) 
p.x # => x 

EDIT 2: Hashes cũng có thể được sử dụng để tìm kiếm đối tượng một cách nhanh chóng. obj_hashed_by_name[name] có thể nhanh hơn nhiều so với obj_array.find { |a| a.name == name }.

+1

tôi vẫn thấy không có lý do không thể truy xuất các cặp thành viên, giá trị dưới dạng băm. đặc biệt là xem xét một cấu trúc không có vấn đề gì với hành động như một mảng, mà tôi tìm thấy gọn gàng ở lần, nhưng nhận được ở các giá trị của một cấu trúc mà không có bối cảnh (các thành viên) chủ yếu có vẻ khá vô dụng với tôi. – cvshepherd

2

Tôi đoán Tôi không biết lý do tại sao bạn muốn làm điều đó một trong hai, nhưng:

s.members.inject({}) { |m, f| m[f] = s[f]; m } 

Hoặc, sử dụng each_with_object:

s.members.each_with_object({}) { |m, h| h[m] = s[m] } 
+0

lý do tôi cần/muốn điều này, là để có thể sắp xếp theo giá trị, mà một hash hiện khá độc đáo. – cvshepherd

+1

@cvshepherd Ah.Tôi đoán tôi đã sử dụng một lớp rồi, nhưng bây giờ tôi đã nhận được nó :) –

0

Câu trả lời được chấp nhận không làm việc cho tôi, tôi sử dụng sau đây thay vì

require 'ostruct' 
require 'date' 

lid = OpenStruct.new(:status=>0,:rowversion=>0,:cre_dt=>DateTime.now.to_date,:cre_user=>'9999999') 
p Hash[lid.each_pair.to_a] #=> {} 
p lid.marshal_dump #=>{:status=>0, :rowversion=>0, :cre_dt=>#<Date: 2014-03-03 ((2456720j,0s,0n),+0s,2299161j)>, :cre_user=>"9999999"} 
Các vấn đề liên quan