Når bør jeg bruke Struct vs. OpenStruct?

stemmer
164

Generelt er det som er fordeler og ulemper ved å bruke en OpenStruct i forhold til en Struct? Hva slags generell bruk-tilfeller ville passe hver av disse?

Publisert på 24/07/2009 klokken 13:18
kilden bruker
På andre språk...                            


8 svar

stemmer
157

Med en OpenStruct, kan du vilkårlig opprette attributter. En Struct, på den annen side må ha sine attributter definert når du oppretter den. Valget av en over den andre bør være basert hovedsakelig på om du trenger å være i stand til å legge til attributter senere.

Måten å tenke på dem som er middelvei av spektret mellom hashes på den ene siden og på den andre klasser. De innebærer et mer konkret forhold blant de data enn gjør en Hash, men de har ikke instansmetoder som ville en klasse. En haug av muligheter for en funksjon, for eksempel, gir mening i en hash; de er bare løst knyttet. Et navn, e-post og telefonnummeret som trengs av en funksjon kan pakkes sammen i en Structeller OpenStruct. Hvis det navnet, e-post og telefonnummer trengs metoder for å gi navnet på både "First Siste" og "Last First" formater, bør du lage en klasse til å håndtere det.

Svarte 24/07/2009 kl. 13:43
kilden bruker

stemmer
79

Andre benchmark:

require 'benchmark'
require 'ostruct'

REP = 100000

User = Struct.new(:name, :age)

USER = "User".freeze
AGE = 21
HASH = {:name => USER, :age => AGE}.freeze

Benchmark.bm 20 do |x|
  x.report 'OpenStruct slow' do
    REP.times do |index|
       OpenStruct.new(:name => "User", :age => 21)
    end
  end

  x.report 'OpenStruct fast' do
    REP.times do |index|
       OpenStruct.new(HASH)
    end
  end

  x.report 'Struct slow' do
    REP.times do |index|
       User.new("User", 21)
    end
  end

  x.report 'Struct fast' do
    REP.times do |index|
       User.new(USER, AGE)
    end
  end
end

For de utålmodige som ønsker å få et inntrykk av benchmark resultater, uten å kjøre dem selv, her er resultatet av koden ovenfor (på en MB Pro 2,4 GHz i7)

                          user     system      total        real
OpenStruct slow       4.430000   0.250000   4.680000 (  4.683851)
OpenStruct fast       4.380000   0.270000   4.650000 (  4.649809)
Struct slow           0.090000   0.000000   0.090000 (  0.094136)
Struct fast           0.080000   0.000000   0.080000 (  0.078940)
Svarte 16/12/2010 kl. 09:20
kilden bruker

stemmer
54

OPPDATER:

Per Ruby 2.4.1 OpenStruct og Struct er mye nærmere i fart. se https://stackoverflow.com/a/43987844/128421

TIDLIGERE:

For fullstendig: Struct vs klasse vs Hash vs. OpenStruct

Løpe samme kode som burtlo s, på Ruby 1.9.2, (1 til 4 kjerner x86_64, 8GB RAM) [tabell redigert for å justere kolonner]:

skaper 1 Mio Structs: 1,43 sek, 219 MB / 90MB (virt / res)
skaper 1 Mio klasse tilfeller: 1,43 sek, 219 MB / 90MB (virt / res)
skaper 1 Mio hashes: 4,46 sek, 493 MB / 364MB (Virt / res)
skaper 1 Mio OpenStructs: 415,13 sek, 2464 MB / 2.3GB (virt / res) # ~ 100x tregere enn hashes
skaper 100K OpenStructs: 10,96 sek, 369 MB / 242MB (Virt / res)

OpenStructs er sloooooow og minneintensive , og ikke skalere godt for store datasett

Opprette 1 Mio OpenStructs er ~ 100x tregere enn å lage 1 Mio hashes .

start = Time.now

collection = (1..10**6).collect do |i|
  {:name => "User" , :age => 21}
end; 1

stop = Time.now

puts "#{stop - start} seconds elapsed"
Svarte 26/03/2011 kl. 02:51
kilden bruker

stemmer
30

Brukstilfeller for de to er ganske forskjellige.

Du kan tenke på det Struct klasse i Ruby 1.9 som tilsvarer structerklæring i C. I Ruby Struct.newtar et sett med feltnavn som argumenter og returnerer en ny klasse. Tilsvarende, i C, en structtar erklæring et sett med felt og lar programmereren å bruke det nye komplekset typen akkurat som han ville noen innebygd type.

Rubin:

Newtype = Struct.new(:data1, :data2)
n = Newtype.new

C:

typedef struct {
  int data1;
  char data2;
} newtype;

newtype n;

Den OpenStruct klasse kan sammenlignes med en anonym struct erklæring i C. Det gjør det mulig for programmereren å opprette en forekomst av en sammensatt type.

Rubin:

o = OpenStruct.new(data1: 0, data2: 0) 
o.data1 = 1
o.data2 = 2

C:

struct {
  int data1;
  char data2;
} o;

o.data1 = 1;
o.data2 = 2;

Her er noen vanlige bruksområder.

OpenStructs kan brukes til å enkelt konvertere hashes til engangs gjenstander som reagerer på alle hash tastene.

h = { a: 1, b: 2 }
o = OpenStruct.new(h)
o.a = 1
o.b = 2

Structs kan være nyttig for forkortelsene klassedefinisjoner.

class MyClass < Struct.new(:a,:b,:c)
end

m = MyClass.new
m.a = 1
Svarte 13/07/2012 kl. 21:36
kilden bruker

stemmer
23

OpenStructs bruke betydelig mer minne og er tregere utøvere versus Structs.

require 'ostruct' 

collection = (1..100000).collect do |index|
   OpenStruct.new(:name => "User", :age => 21)
end

På mitt system følgende kode utført i 14 sekunder og forbrukes 1,5 GB minne. Din kjørelengde kan variere:

User = Struct.new(:name, :age)

collection = (1..100000).collect do |index|
   User.new("User",21)
end

Det ferdig nesten umiddelbart og forbrukes 26,6 MB minne.

Svarte 09/11/2010 kl. 19:56
kilden bruker

stemmer
5

Ta en titt på API med hensyn til den nye metoden. Mye av forskjellene kan finnes der.

Personlig, jeg liker ganske OpenStruct, som jeg ikke trenger å definere strukturen av objektet forhånd, og bare legge ting som jeg ønsker. Jeg tror det ville være den viktigste (dis) fordelen?

Svarte 24/07/2009 kl. 13:25
kilden bruker

stemmer
4

Struct:

>> s = Struct.new(:a, :b).new(1, 2)
=> #<struct a=1, b=2>
>> s.a
=> 1
>> s.b
=> 2
>> s.c
NoMethodError: undefined method `c` for #<struct a=1, b=2>

OpenStruct:

>> require 'ostruct'
=> true
>> os = OpenStruct.new(a: 1, b: 2)
=> #<OpenStruct a=1, b=2>
>> os.a
=> 1
>> os.b
=> 2
>> os.c
=> nil
Svarte 22/05/2017 kl. 20:42
kilden bruker

stemmer
3

Bruke @Robert kode, legger jeg Hashie :: Mash til referanse element og fikk dette resultatet:

                           user     system      total        real
Hashie::Mash slow      3.600000   0.000000   3.600000 (  3.755142)
Hashie::Mash fast      3.000000   0.000000   3.000000 (  3.318067)
OpenStruct slow       11.200000   0.010000  11.210000 ( 12.095004)
OpenStruct fast       10.900000   0.000000  10.900000 ( 12.669553)
Struct slow            0.370000   0.000000   0.370000 (  0.470550)
Struct fast            0.140000   0.000000   0.140000 (  0.145161)
Svarte 30/03/2014 kl. 11:15
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more