it-swarm.com.de

Hash auf eine bedingte Weise erstellen

Ich verwende Ruby on Rails 3.0.10 und möchte ein Hash-Wert-Wert-Paar auf eine bedingte Weise erstellen. Das heißt, ich möchte einen Schlüssel und den zugehörigen Wert hinzufügen, wenn eine Bedingung erfüllt ist:

hash = {
  :key1 => value1,
  :key2 => value2, # This key2\value2 pair should be added only 'if condition' is 'true'
  :key3 => value3,
  ...
}

Wie kann ich das machen und eine "gute" Lesbarkeit für den Code halten? Bin ich gezwungen, die merge-Methode zu verwenden?

35
Backo

Ich bevorzuge tap, da ich denke, dass dies eine sauberere Lösung als die hier beschriebenen ist, da keine hackenden Elemente gelöscht werden müssen und der Umfang, in dem der Hash erstellt wird, klar definiert wird.

Das bedeutet auch, dass Sie keine unnötige lokale Variable deklarieren müssen, die ich immer hasse.

Falls Sie es noch nicht gefunden haben, ist tap sehr einfach - es ist eine Methode von Object, die einen Block akzeptiert und immer das Objekt zurückgibt, für das es aufgerufen wurde. Um einen Hash bedingt aufzubauen, können Sie folgendes tun:

Hash.new.tap do |my_hash|
  my_hash[:x] = 1 if condition_1
  my_hash[:y] = 2 if condition_2
  ...
end

Es gibt viele interessante Anwendungen für tap, dies ist nur eine davon.

53
Russell

Ein funktionaler Ansatz:

hash = {
  :key1 => 1,
  :key2 => (2 if condition),
  :key3 => 3,
}.compact 

Hinweis: Ersetzen Sie für Ruby <2.4.0 oder ohne aktive Unterstützung .compact durch .reject { |k, v| v.nil? }.

24
tokland

Wahrscheinlich am besten, um es einfach zu halten, wenn es um Lesbarkeit geht:

hsh = {}
hsh[:key1] = value1
hsh[:key2] = value2 if condition?
hsh[:key3] = value3
...
8
dwhalen

Ich verwende merge und den ternären Operator für diese Situation.

hash = {
  :key1 => value1,
  :key3 => value3,
  ...
}.merge(condition ? {:key2 => value2} : {})
3
Dave Morse

Halte es einfach:

hash = {
  :key1 => value1,
  :key3 => value3,
  ...
}
hash[:key2]=value2 if condition

Auf diese Weise trennen Sie Ihren speziellen Fall auch visuell, was möglicherweise unbemerkt bleibt, wenn er in einer Hash-Zuweisung eingebettet ist.

3

Bauen Sie zuerst Ihren Hash so auf:

hash = {
  :key1 => value1,
  :key2 => condition ? value2 : :delete_me,
  :key3 => value3
}

Dann machen Sie dies, nachdem Sie Ihren Hash erstellt haben:

hash.delete_if {|_, v| v == :delete_me}

Wenn Ihr Hash nicht eingefroren oder anderweitig unveränderlich ist, bleiben tatsächlich nur die vorhandenen Werte erhalten.

2

WENN Sie einen Hash aus einer Art von Enumerable-Daten erstellen, können Sie zum Beispiel den Befehl inject verwenden:

raw_data.inject({}){ |a,e| a[e.name] = e.value if expr; a }
1
Dmitry Maksimov

So einfach ist das: 

hash = {
  :key1 => value1,
  **(condition ? {key2: value2} : {})
}

Ich hoffe es hilft!

1
Dusht

Die Verwendung von fetch kann nützlich sein, wenn Sie einen Hash aus optionalen Attributen an anderer Stelle auffüllen. Schau dir dieses Beispiel an:

def create_watchable_data(attrs = {})
  return WatchableData.new({
    id:             attrs.fetch(:id, '/catalog/titles/breaking_bad_2_737'),
    titles:         attrs.fetch(:titles, ['737']),
    url:            attrs.fetch(:url, 'http://www.netflix.com/shows/breaking_bad/3423432'),
    year:           attrs.fetch(:year, '1993'),
    watchable_type: attrs.fetch(:watchable_type, 'Show'),
    season_title:   attrs.fetch(:season_title, 'Season 2'),
    show_title:     attrs.fetch(:id, 'Breaking Bad')
  })
end
0
Excalibur