@JanDvorak Cette question ne concerne pas seulement le retour de subhash, mais aussi la modification de celui existant. Des choses très similaires, mais ActiveSupport a différents moyens pour les gérer.
skalee
Réponses:
59
Si vous souhaitez spécifiquement que la méthode renvoie les éléments extraits mais que h1 reste le même:
Ceci est O (n2) - vous aurez une boucle sur le select, une autre boucle sur l'inclusion qui sera appelée h1.size times.
metakungfu
1
Bien que cette réponse soit correcte pour le rubis pur, si vous utilisez des rails, la réponse ci-dessous (en utilisant intégré sliceou except, selon vos besoins) est beaucoup plus propre
Krease
137
ActiveSupport, Au moins depuis 2.3.8, fournit quatre méthodes pratiques: #slice, #exceptet leurs homologues destructeurs: #slice!et #except!. Ils ont été mentionnés dans d'autres réponses, mais pour les résumer en un seul endroit:
Notez les valeurs de retour des méthodes bang. Ils vont non seulement personnaliser le hachage existant, mais également renvoyer les entrées supprimées (non conservées). Le Hash#except!mieux correspond à l'exemple donné dans la question:
x ={a:1, b:2, c:3, d:4}# => {:a=>1, :b=>2, :c=>3, :d=>4}
x.except!(:c,:d)# => {:a=>1, :b=>2}
x
# => {:a=>1, :b=>2}
ActiveSupportne nécessite pas de rails entiers, est assez léger. En fait, beaucoup de gemmes non-rails en dépendent, donc vous l'avez probablement déjà dans Gemfile.lock. Pas besoin d'étendre la classe Hash par vous-même.
Les correctifs Mokey sont certainement la voie à suivre pour l'OMI. Beaucoup plus propre et rend l'intention plus claire.
Romário
1
Ajouter pour modifier le code pour adresser correctement le module principal, définir le module et importer étendre Hash core ... module CoreExtensions module Hash def slice (* keys) :: Hash [[keys, self.values_at (* keys)]. Transpose] end end end Hash.include CoreExtensions :: Hash
Je pense que vous décrivez l'extrait !. extrait! supprime les clés du hachage initial, renvoyant un nouveau hachage contenant les clés supprimées. tranche! fait le contraire: supprimer toutes les clés sauf les clés spécifiées du hachage initial (encore une fois, renvoyer un nouveau hachage contenant les clés supprimées). Alors tranche! est un peu plus comme une opération "retenir".
Voici une solution fonctionnelle qui peut être utile si vous n'utilisez pas Ruby 2.5 et dans le cas où vous ne voudriez pas polluer votre classe Hash en ajoutant une nouvelle méthode:
Juste un ajout à la méthode slice, si les clés de sous-hachage que vous souhaitez séparer du hachage d'origine vont être dynamiques, vous pouvez faire comme,
slice(*dynamic_keys)# dynamic_keys should be an array type
Réponses:
Si vous souhaitez spécifiquement que la méthode renvoie les éléments extraits mais que h1 reste le même:
Et si vous voulez patcher cela dans la classe Hash:
Si vous souhaitez simplement supprimer les éléments spécifiés du hachage, c'est beaucoup plus facile en utilisant delete_if .
la source
slice
ouexcept
, selon vos besoins) est beaucoup plus propreActiveSupport
, Au moins depuis 2.3.8, fournit quatre méthodes pratiques:#slice
,#except
et leurs homologues destructeurs:#slice!
et#except!
. Ils ont été mentionnés dans d'autres réponses, mais pour les résumer en un seul endroit:Notez les valeurs de retour des méthodes bang. Ils vont non seulement personnaliser le hachage existant, mais également renvoyer les entrées supprimées (non conservées). Le
Hash#except!
mieux correspond à l'exemple donné dans la question:ActiveSupport
ne nécessite pas de rails entiers, est assez léger. En fait, beaucoup de gemmes non-rails en dépendent, donc vous l'avez probablement déjà dans Gemfile.lock. Pas besoin d'étendre la classe Hash par vous-même.la source
x.except!(:c, :d)
(avec bang) devrait être# => {:a=>1, :b=>2}
. Tant mieux si vous pouvez modifier votre réponse.Si vous utilisez des rails , Hash # slice est la voie à suivre.
Si vous n'utilisez pas de rails , Hash # values_at renverra les valeurs dans le même ordre que vous leur avez demandé afin que vous puissiez faire ceci:
ex:
Explication:
Hors de
{:a => 1, :b => 2, :c => 3}
nous voulons{:a => 1, :b => 2}
Si vous sentez que le patching de singe est la voie à suivre, voici ce que vous voulez:
la source
Ruby 2.5 a ajouté Hash # slice :
la source
Vous pouvez utiliser slice! (* Keys) qui est disponible dans les extensions principales d'ActiveSupport
initial_hash serait maintenant
extrait_slide serait maintenant
Vous pouvez regarder
slice.rb in ActiveSupport 3.1.3
la source
la source
def subhash(*keys) select {|k,v| keys.include?(k)} end
la source
si vous utilisez des rails, il peut être pratique d'utiliser Hash.except
la source
la source
Voici une comparaison rapide des performances des méthodes suggérées,
#select
semble être la plus rapideLe raffinement ressemblera à ceci:
Et pour l'utiliser:
la source
Les deux
delete_if
etkeep_if
font partie du noyau Ruby. Ici, vous pouvez réaliser ce que vous souhaitez sans patcher leHash
type.Pour plus d'informations, consultez les liens ci-dessous dans la documentation:
la source
Comme d'autres l'ont mentionné, Ruby 2.5 a ajouté la méthode Hash # slice.
Rails 5.2.0beta1 a également ajouté sa propre version de Hash # slice pour modifier la fonctionnalité pour les utilisateurs du framework qui utilisent une version antérieure de Ruby. https://github.com/rails/rails/commit/01ae39660243bc5f0a986e20f9c9bff312b1b5f8
Si vous cherchez à mettre en œuvre le vôtre pour une raison quelconque, c'est également une belle ligne:
la source
Ce code injecte la fonctionnalité que vous demandez dans la classe Hash:
et produit les résultats que vous avez fournis:
Remarque: cette méthode retourne en fait les clés / valeurs extraites.
la source
Voici une solution fonctionnelle qui peut être utile si vous n'utilisez pas Ruby 2.5 et dans le cas où vous ne voudriez pas polluer votre classe Hash en ajoutant une nouvelle méthode:
Ensuite, vous pouvez l'appliquer même sur des hachages imbriqués:
la source
Juste un ajout à la méthode slice, si les clés de sous-hachage que vous souhaitez séparer du hachage d'origine vont être dynamiques, vous pouvez faire comme,
la source
Nous pouvons le faire en boucle sur les clés que nous voulons extraire et en vérifiant simplement que la clé existe, puis en l'extrayant.
la source