ruby - aws - athena data types



Rechercher des paires clé/valeur au sein d'un hachage contenant un nombre arbitraire de hachages imbriqués et de tableaux (6)

Bien que cela semble être un problème courant, je viens de passer un peu de temps à essayer de trouver / trouver exactement ce dont j'ai besoin, ce qui, à mon avis, correspond à vos besoins. Aucun des liens de la première réponse n’est précis.

class Hash
  def deep_find(key)
    key?(key) ? self[key] : self.values.inject(nil) {|memo, v| memo ||= v.deep_find(key) if v.respond_to?(:deep_find) }
  end
end

Donc donné:

hash = {:get_transaction_list_response => { :get_transaction_list_return => { :transaction => [ { ... 

Le suivant:

hash.deep_find(:transaction)

trouvera le tableau associé à la clé: transaction.

Ce n'est pas optimal car l'injection continuera à itérer même si le mémo est rempli.

https://ffff65535.com

Un service Web renvoie un hachage qui contient un nombre inconnu de hachages imbriqués, dont certains contiennent un tableau, qui à son tour contient un nombre inconnu de hachages imbriqués.

Certaines des clés ne sont pas uniques - c.-à-d. Qu'elles sont présentes dans plus d'un hachage imbriqué.

Cependant, toutes les clés dont je me soucie sont toutes uniques.

Est-ce que je peux donner une clé au hachage de haut niveau, et récupérer sa valeur même si la paire clé-valeur est enfouie au plus profond de ce bourbier?

(Le service Web est Amazon Product Advertising API, qui modifie légèrement la structure des résultats en fonction du nombre de résultats et des types de recherche autorisés dans chaque catégorie de produit.)


Comme Rails 5 ActionController :: Parameters ne hérite plus de Hash, j'ai dû modifier la méthode et la rendre spécifique aux paramètres.

module ActionController
  class Parameters
    def deep_find(key, object=self, found=nil)
      if object.respond_to?(:key?) && object.key?(key)
        return object[key]
      elsif object.respond_to?(:each)
        object = object.to_unsafe_h if object.is_a?(ActionController::Parameters)
        object.find { |*a| found = deep_find(key, a.last) }
        return found
      end
    end
  end
end

Si la clé est trouvée, elle renvoie la valeur de cette clé, mais elle ne retourne pas d'objet ActionController :: Parameter afin que les paramètres forts ne soient pas conservés.


J'ai fini par utiliser ceci pour une petite recherche de trie que j'ai écrite:

def trie_search(str, obj=self)
  if str.length <= 1
    obj[str]
  else
    str_array = str.chars
    next_trie = obj[str_array.shift]
    next_trie ? trie_search(str_array.join, next_trie) : nil
  end
end

Note: c'est juste pour les hachages imbriqués pour le moment. Actuellement aucun support de tableau.


J'utilise le code suivant

def search_hash(hash, key)
  return hash[key] if hash.assoc(key)
  hash.delete_if{|key, value| value.class != Hash}
  new_hash = Hash.new
  hash.each_value {|values| new_hash.merge!(values)}
  unless new_hash.empty?
    search_hash(new_hash, key)
  end
end

Une variante de la solution de Barelyknown: elle trouvera toutes les valeurs d’une clé dans un hash plutôt que la première.

class Hash
  def deep_find(key, object=self, found=[])
    if object.respond_to?(:key?) && object.key?(key)
      found << object[key]
    end
    if object.is_a? Enumerable
      found << object.collect { |*a| deep_find(key, a.last) }
    end
    found.flatten.compact
  end
end

{a: [{b: 1}, {b: 2}]}.deep_find(:b) retournera [1, 2]


Voici une solution récursive simple:

def nested_hash_value(obj,key)
  if obj.respond_to?(:key?) && obj.key?(key)
    obj[key]
  elsif obj.respond_to?(:each)
    r = nil
    obj.find{ |*a| r=nested_hash_value(a.last,key) }
    r
  end
end

h = { foo:[1,2,[3,4],{a:{bar:42}}] }
p nested_hash_value(h,:bar)
#=> 42




amazon