class Hash

Ein Hash-Objekt ordnet jeden seiner eindeutigen Schlüssel einem bestimmten Wert zu.

Ein Hash hat gewisse Ähnlichkeiten mit einem Array, aber

Hash-Datensyntax

Die ursprüngliche Syntax für einen Hash-Eintrag verwendet den „Hash-Raketen“, =>

h = {:foo => 0, :bar => 1, :baz => 2}
h # => {foo: 0, bar: 1, baz: 2}

Alternativ, aber nur für einen Schlüssel, der ein Symbol ist, können Sie eine neuere JSON-ähnliche Syntax verwenden, bei der jedes Bareword zu einem Symbol wird

h = {foo: 0, bar: 1, baz: 2}
h # => {foo: 0, bar: 1, baz: 2}

Sie können auch einen String anstelle eines Bareword verwenden

h = {'foo': 0, 'bar': 1, 'baz': 2}
h # => {foo: 0, bar: 1, baz: 2}

Und Sie können die Stile mischen

h = {foo: 0, :bar => 1, 'baz': 2}
h # => {foo: 0, bar: 1, baz: 2}

Aber es ist ein Fehler, die JSON-ähnliche Syntax für einen Schlüssel zu versuchen, der kein Bareword oder String ist

# Raises SyntaxError (syntax error, unexpected ':', expecting =>):
h = {0: 'zero'}

Der Wert kann weggelassen werden, was bedeutet, dass der Wert vom Kontext unter dem Namen des Schlüssels abgerufen wird

x = 0
y = 100
h = {x:, y:}
h # => {x: 0, y: 100}

Häufige Verwendungen

Sie können einen Hash verwenden, um Objekten Namen zu geben

person = {name: 'Matz', language: 'Ruby'}
person # => {name: "Matz", language: "Ruby"}

Sie können einen Hash verwenden, um Method-Argumenten Namen zu geben

def some_method(hash)
  p hash
end
some_method({foo: 0, bar: 1, baz: 2}) # => {foo: 0, bar: 1, baz: 2}

Hinweis: Wenn das letzte Argument in einem Methodenaufruf ein Hash ist, können die geschweiften Klammern weggelassen werden

some_method(foo: 0, bar: 1, baz: 2) # => {foo: 0, bar: 1, baz: 2}

Sie können einen Hash verwenden, um ein Objekt zu initialisieren

class Dev
  attr_accessor :name, :language
  def initialize(hash)
    self.name = hash[:name]
    self.language = hash[:language]
  end
end
matz = Dev.new(name: 'Matz', language: 'Ruby')
matz # => #<Dev: @name="Matz", @language="Ruby">

Erstellen eines Hash

Sie können ein Hash-Objekt explizit mit

Sie können bestimmte Objekte mit umwandeln

Sie können einen Hash erstellen, indem Sie die Methode Hash.new aufrufen

# Create an empty hash.
h = Hash.new
h # => {}
h.class # => Hash

Sie können einen Hash erstellen, indem Sie die Methode Hash.[] aufrufen

# Create an empty hash.
h = Hash[]
h # => {}
# Create a hash with initial entries.
h = Hash[foo: 0, bar: 1, baz: 2]
h # => {foo: 0, bar: 1, baz: 2}

Sie können einen Hash erstellen, indem Sie seine Literalform (geschweifte Klammern) verwenden

# Create an empty hash.
h = {}
h # => {}
# Create a +Hash+ with initial entries.
h = {foo: 0, bar: 1, baz: 2}
h # => {foo: 0, bar: 1, baz: 2}

Hash-Wert-Grundlagen

Der einfachste Weg, einen Hash-Wert abzurufen (Instanzmethode [])

h = {foo: 0, bar: 1, baz: 2}
h[:foo] # => 0

Der einfachste Weg, einen Hash-Wert zu erstellen oder zu aktualisieren (Instanzmethode []=)

h = {foo: 0, bar: 1, baz: 2}
h[:bat] = 3 # => 3
h # => {foo: 0, bar: 1, baz: 2, bat: 3}
h[:foo] = 4 # => 4
h # => {foo: 4, bar: 1, baz: 2, bat: 3}

Der einfachste Weg, einen Hash-Eintrag zu löschen (Instanzmethode delete)

h = {foo: 0, bar: 1, baz: 2}
h.delete(:bar) # => 1
h # => {foo: 0, baz: 2}

Eintragsreihenfolge

Ein Hash-Objekt präsentiert seine Einträge in der Reihenfolge ihrer Erstellung. Dies ist sichtbar in

Ein neuer Hash hat seine anfängliche Reihenfolge gemäß den angegebenen Einträgen

h = Hash[foo: 0, bar: 1]
h # => {foo: 0, bar: 1}

Neue Einträge werden am Ende hinzugefügt

h[:baz] = 2
h # => {foo: 0, bar: 1, baz: 2}

Das Aktualisieren eines Wertes beeinflusst nicht die Reihenfolge

h[:baz] = 3
h # => {foo: 0, bar: 1, baz: 3}

Aber das Neuerstellen eines gelöschten Eintrags kann die Reihenfolge beeinflussen

h.delete(:foo)
h[:foo] = 5
h # => {bar: 1, baz: 3, foo: 5}

Hash Schlüssel

Hash Schlüssel-Äquivalenz

Zwei Objekte werden als derselbe Hash-Schlüssel behandelt, wenn ihr hash-Wert identisch ist und die beiden Objekte eql? zueinander sind.

Ändern eines aktiven Hash-Schlüssels

Das Ändern eines Hash-Schlüssels, während er in Gebrauch ist, beschädigt den Index des Hash.

Dieser Hash hat Schlüssel, die Arrays sind

a0 = [ :foo, :bar ]
a1 = [ :baz, :bat ]
h = {a0 => 0, a1 => 1}
h.include?(a0) # => true
h[a0] # => 0
a0.hash # => 110002110

Das Ändern eines Array-Elements a0[0] ändert seinen Hash-Wert

a0[0] = :bam
a0.hash # => 1069447059

Und beschädigt den Hash-Index

h.include?(a0) # => false
h[a0] # => nil

Sie können den Hash-Index mit der Methode rehash reparieren

h.rehash # => {[:bam, :bar]=>0, [:baz, :bat]=>1}
h.include?(a0) # => true
h[a0] # => 0

Ein String-Schlüssel ist immer sicher. Das liegt daran, dass ein nicht eingefrorener String, der als Schlüssel übergeben wird, durch eine duplizierte und eingefrorene String ersetzt wird

s = 'foo'
s.frozen? # => false
h = {s => 0}
first_key = h.keys.first
first_key.frozen? # => true

Benutzerdefinierte Hash-Schlüssel

Um als Hash-Schlüssel verwendbar zu sein, müssen Objekte die Methoden hash und eql? implementieren. Hinweis: Diese Anforderung gilt nicht, wenn der Hash compare_by_identity verwendet, da der Vergleich dann auf der Objekt-ID der Schlüssel anstelle von hash und eql? beruht.

Object definiert eine grundlegende Implementierung für hash und eq?, die jedes Objekt zu einem eigenständigen Schlüssel macht. Typischerweise möchten benutzerdefinierte Klassen diese Methoden überschreiben, um sinnvolles Verhalten zu bieten, oder z. B. Struct erben, das nützliche Definitionen dafür hat.

Eine typische Implementierung von hash basiert auf den Daten des Objekts, während eql? normalerweise mit der überschriebenen ==-Methode verknüpft ist

class Book
  attr_reader :author, :title

  def initialize(author, title)
    @author = author
    @title = title
  end

  def ==(other)
    self.class === other &&
      other.author == @author &&
      other.title == @title
  end

  alias eql? ==

  def hash
    [self.class, @author, @title].hash
  end
end

book1 = Book.new 'matz', 'Ruby in a Nutshell'
book2 = Book.new 'matz', 'Ruby in a Nutshell'

reviews = {}

reviews[book1] = 'Great reference!'
reviews[book2] = 'Nice and compact!'

reviews.length #=> 1

Schlüssel nicht gefunden?

Wenn eine Methode versucht, den Wert für einen Schlüssel abzurufen und zurückzugeben, und dieser Schlüssel *gefunden wird*, ist der zurückgegebene Wert der dem Schlüssel zugeordnete Wert.

Aber was ist, wenn der Schlüssel *nicht gefunden wird*? In diesem Fall geben bestimmte Methoden einen Standardwert zurück, während andere einen KeyError auslösen.

Nil-Rückgabewert

Wenn Sie möchten, dass für einen nicht gefundenen Schlüssel nil zurückgegeben wird, können Sie aufrufen

Sie können diese Verhaltensweisen für [], dig und values_at (aber nicht für assoc) überschreiben; siehe Hash-Standard.

KeyError

Wenn Sie möchten, dass für einen nicht gefundenen Schlüssel ein KeyError ausgelöst wird, können Sie aufrufen

Hash-Standard

Für bestimmte Methoden ([], dig und values_at) wird der Rückgabewert für einen nicht gefundenen Schlüssel durch zwei Hash-Eigenschaften bestimmt

Im einfachen Fall sind beide Werte nil, und die Methoden geben nil für einen nicht gefundenen Schlüssel zurück; siehe Nil-Rückgabewert oben.

Beachten Sie, dass dieser gesamte Abschnitt („Hash-Standard“)

Standard für beliebigen Schlüssel

Sie können einen beliebigen Schlüssel-Standard für einen Hash definieren; das heißt, einen Wert, der für *jeden* nicht gefundenen Schlüssel zurückgegeben wird

Sie können den Standardwert beim Erstellen des Hash mit Hash.new und der Option default_value, oder später mit der Methode default= setzen.

Hinweis: Obwohl der Wert von default jedes Objekt sein kann, ist es möglicherweise keine gute Idee, ein veränderliches Objekt zu verwenden.

Schlüssel-spezifische Standards

Sie können einen schlüssel-spezifischen Standard für einen Hash definieren; das heißt, ein Proc, das basierend auf dem Schlüssel selbst einen Wert zurückgibt.

Sie können den Standard-Proc beim Erstellen des Hash mit Hash.new und einem Block, oder später mit der Methode default_proc= setzen.

Beachten Sie, dass der Proc self ändern kann, aber das Ändern von self auf diese Weise ist nicht threadsicher; mehrere Threads können gleichzeitig den Standard-Proc für denselben Schlüssel aufrufen.

Methoden-Standard

Für zwei Methoden können Sie einen Standardwert für einen nicht gefundenen Schlüssel angeben, der nur für einen einzigen Methodenaufruf wirksam ist (und nicht für nachfolgende Aufrufe)

Was gibt es hier

Zuerst, was anderswo ist. Klasse Hash

Hier bietet die Klasse Hash Methoden, die nützlich sind für

Die Klasse Hash enthält auch Methoden aus dem Modul Enumerable.

Methoden zum Erstellen eines Hash

Methoden zum Festlegen des Hash-Zustands

Methoden zum Abfragen

Methoden zum Vergleichen

Methoden zum Abrufen

Methoden zum Zuweisen

Methoden zum Löschen

Diese Methoden entfernen Einträge aus self

Diese Methoden geben eine Kopie von self mit einigen entfernten Einträgen zurück

Methoden zur Iteration

Methoden zur Konvertierung

Methoden zum Umwandeln von Schlüsseln und Werten