Quand utiliser Struct au lieu de Hash dans Ruby?

Je n’ai pas beaucoup d’expérience en programmation. Mais pour moi, Struct semble quelque peu similaire à Hash.

  • Qu’est-ce que Struct peut bien faire?
  • Y a-t-il quelque chose que Struct peut faire, que Hash ne peut pas faire?

Après googling, le concept de Struct est important en C, mais je ne connais pas grand chose en C.

Les structures diffèrent de l’utilisation des hashmaps des manières suivantes (en plus de l’aspect du code):

  • Une structure a un ensemble fixe d’atsortingbuts, tandis que vous ajoutez de nouvelles clés à un hachage.
  • L’appel d’un atsortingbut qui n’existe pas sur une instance d’une structure provoquera une erreur NoMethodError, tandis que l’obtention de la valeur d’une clé non existante à partir d’un hachage renverra simplement zéro.
  • Deux instances de structures différentes ne seront jamais égales même si les structures ont les mêmes atsortingbuts et que les instances ont les mêmes valeurs (par exemple, Struct.new(:x).new(42) == Struct.new(:x).new(42) est faux, alors que Foo = Struct.new(:x); Foo.new(42)==Foo.new(42) est vrai).
  • La méthode to_a pour les structures renvoie un tableau de valeurs, tandis que to_a sur un hachage vous donne un tableau de paires clé-valeur (où “paire” signifie “tableau à deux éléments”)
  • Si Foo = Struct.new(:x, :y, :z) vous pouvez faire Foo.new(1,2,3) pour créer une instance de Foo sans avoir à épeler les noms d’atsortingbuts.

Donc, pour répondre à la question: Lorsque vous souhaitez modéliser des objects avec un ensemble d’atsortingbuts connus, utilisez des structures. Lorsque vous voulez modéliser une utilisation arbitraire des hashmaps (par exemple, compter combien de fois chaque mot apparaît dans une chaîne ou mapper des pseudonymes sur des noms complets, etc., ce ne sont certainement pas des tâches pour une structure avec un nom, une un ajustement parfait pour Person = Struct.new(name, age, address) ).

En guise de remarque: les structures C ont peu à voir avec les structures ruby, alors ne vous laissez pas décourager par cela.

Je sais que cette question a été très bien traitée, mais étonnamment, personne n’a parlé de l’une des plus grandes différences et des avantages réels de Struct . Et je suppose que c’est pourquoi quelqu’un demande encore .

Je comprends les différences, mais quel est le véritable avantage d’utiliser un Struct over a Hash, lorsqu’un Hash peut faire la même chose, et est plus simple à gérer? On dirait que Structs est un peu superflu.

Struct est plus rapide .

 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) 

À partir de la documentation Struct :

Un Struct est un moyen pratique de regrouper un certain nombre d’atsortingbuts, en utilisant des méthodes d’accesseur, sans avoir à écrire une classe explicite.

Par contre, un Hash :

Un hachage est une collection de paires clé-valeur. Il est similaire à un tableau, sauf que l’indexation se fait via des clés arbitraires de n’importe quel type d’object, et non un index entier. L’ordre dans lequel vous traversez un hachage par clé ou valeur peut sembler arbitraire et ne sera généralement pas dans l’ordre d’insertion.

La principale différence réside dans la manière dont vous accédez à vos données.

 ruby-1.9.1-p378 > Point = Struct.new(:x, :y) => Point ruby-1.9.1-p378 > p = Point.new(4,5) => # ruby-1.9.1-p378 > px => 4 ruby-1.9.1-p378 > py => 5 ruby-1.9.1-p378 > p = {:x => 4, :y => 5} => {:x=>4, :y=>5} ruby-1.9.1-p378 > px 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 `
' ruby-1.9.1-p378 > p[:x] => 4 ruby-1.9.1-p378 > p[:y] => 5

En bref, vous feriez une nouvelle structure quand vous voulez une classe qui est une structure “plain old data” (avec éventuellement l’intention de l’étendre avec plus de méthodes), et vous utiliseriez un Hash quand vous n’avez pas besoin d’un type formel du tout.

Une autre différence principale est que vous pouvez append des méthodes de comportement à une structure.

  Customer = Struct.new(:name, :address) do def greeting; "Hello #{name}!" ; end end Customer.new("Dave", "123 Main").greeting # => "Hello Dave!" 

Si vous voulez simplement encapsuler les données, un hachage (ou un tableau de hachages) convient. Si vous prévoyez de manipuler les données ou d’interagir avec d’autres données, un Struct peut ouvrir des possibilités intéressantes:

 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