【发布时间】:2011-03-17 13:52:17
【问题描述】:
我没有太多的编程经验。但是,在我看来,Struct 似乎有点类似于 Hash。
- Struct 能做什么好?
- 有什么 Struct 能做而 Hash 不能做的事吗?
google了一下,Struct的概念在C中很重要,但是我对C了解不多。
【问题讨论】:
我没有太多的编程经验。但是,在我看来,Struct 似乎有点类似于 Hash。
google了一下,Struct的概念在C中很重要,但是我对C了解不多。
【问题讨论】:
另一个主要区别是您可以向 Struct 添加行为方法。
Customer = Struct.new(:name, :address) do
def greeting; "Hello #{name}!" ; end
end
Customer.new("Dave", "123 Main").greeting # => "Hello Dave!"
【讨论】:
结构与使用哈希图的不同之处在于以下方面(除了代码的外观):
Struct.new(:x).new(42) == Struct.new(:x).new(42) 为假,而Foo = Struct.new(:x); Foo.new(42)==Foo.new(42) 为真)。to_a 方法返回一个值数组,而散列上的to_a 为您提供一个键值对数组(其中“pair”表示“双元素数组”)Foo = Struct.new(:x, :y, :z),您可以使用Foo.new(1,2,3) 创建Foo 的实例,而无需拼出属性名称。所以回答这个问题:当你想用一组已知的属性对对象建模时,使用结构。当您想对任意使用哈希图进行建模时(例如,计算每个单词在字符串中出现的频率或将昵称映射到全名等绝对不是结构的工作,而对具有姓名、年龄和地址的人进行建模将是非常适合Person = Struct.new(name, age, address))。
附带说明:C 结构与 ruby 结构几乎没有关系,所以不要让自己对此感到困惑。
【讨论】:
Struct#== 的工作方式与您实际存储 Struct.new 的结果时所解释的不同,而不是使用两次调用它相同的论点。
Foo = Struct.new(:x); Bar = Struct.new(:x),然后再做Foo.new(42) == Bar.new(42),我会错的。如果我这样做Foo.new(42) == Foo.new(42),我会做到的。如果你仔细阅读,这正是我所说的(不同结构的两个实例“)。
如果您只是要封装数据,那么哈希(或哈希数组)就可以了。如果您打算让数据操作或与其他数据交互,那么 Struct 可以打开一些有趣的可能性:
Point = Struct.new(:x, :y)
point_a = Point.new(0,0)
point_b = Point.new(2,3)
class Point
def distance_to another_point
Math.sqrt((self.x - another_point.x)**2 + (self.y - another_point.y)**2)
end
end
puts point_a.distance_to point_b
【讨论】:
class Point << Hash,一切都会是一样的。
我知道这个问题几乎得到了很好的回答,但令人惊讶的是,没有人谈论 Struct 的最大差异之一和真正的好处。我想这就是为什么somebody is still asking。
我了解其中的区别,但是当 Hash 可以做同样的事情并且更容易处理时,使用 Struct 而不是 Hash 的真正优势是什么?似乎结构有点多余。
Struct更快。
require 'benchmark'
Benchmark.bm 10 do |bench|
bench.report "Hash: " do
50_000_000.times do { name: "John Smith", age: 45 } end
end
bench.report "Struct: " do
klass = Struct.new(:name, :age)
50_000_000.times do klass.new("John Smith", 45) end
end
end
# ruby 2.2.2p95 (2015-04-13 revision 50295) [x64-mingw32].
# user system total real
# Hash: 22.340000 0.016000 22.356000 ( 24.260674)
# Struct: 12.979000 0.000000 12.979000 ( 14.095455)
# ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-darwin11.0]
#
# user system total real
# Hash: 31.980000 0.060000 32.040000 ( 32.039914)
# Struct: 16.880000 0.010000 16.890000 ( 16.886061)
【讨论】:
来自Struct 文档:
Struct 是一种使用访问器方法将多个属性捆绑在一起的便捷方式,而无需编写显式类。
另一方面,Hash:
哈希是键值对的集合。它类似于数组,除了索引是通过任何对象类型的任意键完成的,而不是整数索引。您通过键或值遍历哈希的顺序可能看起来是任意的,并且通常不会在插入顺序中。
主要区别在于您访问数据的方式。
ruby-1.9.1-p378 > Point = Struct.new(:x, :y)
=> Point
ruby-1.9.1-p378 > p = Point.new(4,5)
=> #<struct Point x=4, y=5>
ruby-1.9.1-p378 > p.x
=> 4
ruby-1.9.1-p378 > p.y
=> 5
ruby-1.9.1-p378 > p = {:x => 4, :y => 5}
=> {:x=>4, :y=>5}
ruby-1.9.1-p378 > p.x
NoMethodError: undefined method `x' for {:x=>4, :y=>5}:Hash
from (irb):7
from /Users/mr/.rvm/rubies/ruby-1.9.1-p378/bin/irb:17:in `<main>'
ruby-1.9.1-p378 > p[:x]
=> 4
ruby-1.9.1-p378 > p[:y]
=> 5
简而言之,当你想要一个 "plain old data" structure 的类时,你会创建一个新的 Struct(可以选择使用更多方法来扩展它),当你不需要正式类型时,你会使用 Hash完全没有。
【讨论】: