优化搜索多维ruby哈希的方法

时间:2014-05-19 16:41:33

标签: ruby-on-rails ruby arrays api hash

我正在使用LinkedIn API来获取公司'细节。他们正在发送XML响应,因此我只是使用.to_hash方法将XML转换为哈希 这是我得到的示例哈希:http://pastebin.com/1bXtHZ2F

在一些公司,他们有多个地点和联系信息,我想解析这些数据并获取电话号码,城市,邮政编码等详细信息。

响应的结构不一致。有时位置字段本身丢失或postal_code仅在第四个位置可用。

我尝试了两种方法:

1

def phone(locations)
  (locations && locations["values"][0]["contactInfo"]["phone1"]) || nil
end

如果第一个阵列中没有电话号码

,则无效

2

def phone(locations)
  if locations["locations"]["total"].to_i == 1 
    locations["locations"]["location"]["contact_info"]["phone1"]
  else
    locations["locations"]["location"].each do |p|
      if (!p["contact_info"]["phone1"].nil? || !p['contact_info'].nil?)
        return p["contact_info"]["phone1"]
        break
      end
    end
  end
end

如果响应中缺少"location"哈希本身,则无效。我需要一个解决方案,我可以使用密钥"city""phone""postal_code"进行搜索,并更新是否存在。如果它返回一个数组,则解析数组并获取非空数据。

我也读过StackOverflow answer

2 个答案:

答案 0 :(得分:1)

我认为这是一个关于代码置信度的问题。也就是说,我打赌你可以弄清楚如何在所有可能的条件下猜测你的方式......但这会产生一堆乱七八糟的不自信的代码。自信的代码陈述了它想要的东西,它得到它并继续前进。 (注意:我从这本精彩的书中得到了我对这个主题的所有灵感:Avdi Grimm的http://www.confidentruby.com/

那就是说,我推荐以下内容。

  1. 安装naught gem:https://github.com/avdi/naught
  2. 在您的代码中,使用Maybe转换功能(通过gem documetnation了解信息)可以自信地达到您的价值:
  3. 在班级或管制员的顶层:

    NullObject = Naught.build
    
    include NullObject::Conversions
    

    在你的方法中:

    def phone(locations)
      return {} if locations["location"].blank?
      Maybe(locations["locations"])["location"].to_a.inject({}) do |location, acc|
        contact_info = Maybe(location["contact_info"])
        acc[location][:city] = contact_info["city1"].to_s
        acc[location][:phone] = contact_info["phone1"].to_i
        acc[location][:postal_code] = contact_info["postal_code1"].to_s
        acc
      end
    end
    

    我不确定你要完成什么,但上述情况可能就是一个开始。它只是试图假设所有的密钥都存在。无论是他们还是他们都没有将它们转换为对象(数组,字符串或整数)。然后,最终收集到一个哈希值(调用acc - " accumulator" - 上面的循环内部)的缩写,以便返回。

    如果上述任何需要澄清,请告诉我,我们可以聊天。

答案 1 :(得分:1)

好的,这段代码基本上是通过哈希工作的,并不关心节点名称(除了它搜索的特定节点)

find_and_get_values方法有两个参数:要搜索的对象和要查找的节点数组。如果数组中的所有节点都是同一父节点下的兄弟节点,它将仅返回结果。 (所以“city”和“postal_code”必须在同一个父级之下,否则都不会返回)

返回的数据是一个简单的哈希值。

get_values方法接受一个参数(公司哈希)并调用find_and_get_values两次,一次用于%w(city postal_code),一次用于%w(phone1)并将哈希结果合并到一个哈希中。

def get_values(company)
  answer = {}
  answer.merge!(find_and_get_values(company["locations"], %w(city postal_code))
  answer.merge!(find_and_get_values(company["locations"], ["phone1"]))
  answer
end

def find_and_get_values(source, match_keys)
  return {} if source.nil?
  if source.kind_of?(Array)
    source.each do |sub_source|
      result = find_and_get_values(sub_source, match_keys)
      return result unless result.empty?
    end
  else
    result = {}
    if source.kind_of?(Hash)
      match_keys.each do |key|
        result[key] = source[key] unless source[key].nil?
      end
      return result if result.count == match_keys.count
      source.each do |sub_source|
        result = find_and_get_values(sub_source, match_keys)
        return result unless result.empty?
      end
    end
  end
  return {}
end

  p get_values(company)