2

我有一个 db 查询,它返回如下结果:

db_result.each {|row| puts row}
{"IP"=>"1.2.3.4","Field1"=>"abc","Field2"=>"123"}
{"IP"=>"1.2.3.4","Field1"=>"abc","Field2"=>"234"}
{"IP"=>"1.2.3.4","Field1"=>"bcd","Field2"=>"345"}
{"IP"=>"3.4.5.6","Field1"=>"bcd","Field2"=>"456"}
{"IP"=>"3.4.5.6","Field1"=>"bcd","Field2"=>"567"}

并希望将其放入哈希中,例如:

{
  "1.2.3.4" => {
    "abc" => ["123", "234"],
    "bcd" => "345"
  },
  "3.4.5.6" => {
    "bcd" => ["456", "567"]
  }
}

我目前正在做的是:

result_hash = Hash.new { |h, k| h[k] = {} }
db_result.each do |row|
  result_hash[row["IP"]] = Hash.new { |h, k| h[k] = [] } unless result_hash.has_key? row["IP"]
  result_hash[row["IP"]][row["Field1"]] <<  row["Field2"]
end 

哪个有效,但是想知道是否有更整洁的方法。

4

2 回答 2

1

我同意迈克尔的观点,你的方法没有任何问题。代码背后的意图很容易看出。

如果你想变得花哨,这里有一个(许多)方法:

x = [
  {"IP"=>"1.2.3.4","Field1"=>"abc","Field2"=>"123"},
  {"IP"=>"1.2.3.4","Field1"=>"abc","Field2"=>"234"},
  {"IP"=>"1.2.3.4","Field1"=>"bcd","Field2"=>"345"},
  {"IP"=>"3.4.5.6","Field1"=>"bcd","Field2"=>"456"},
  {"IP"=>"3.4.5.6","Field1"=>"bcd","Field2"=>"567"}
]


y = x.inject({}) do |result, row|
  new_row = result[row["IP"]] ||= {}
  (new_row[row["Field1"]] ||= []) << row["Field2"]

  result
end

我认为这应该产生与您的方法相同的时间复杂度。

于 2012-08-16T15:02:01.150 回答
1

将此视为同行评审。作为处理和维护的建议...

我建议您希望数据结构更加一致。

代替:

{
  "1.2.3.4" => {
    "abc" => ["123", "234"],
    "bcd" => "345"
  },
  "3.4.5.6" => {
    "bcd" => ["456", "567"]
  }
}

我建议:

{
  "1.2.3.4" => {
    "abc" => ["123", "234"],
    "bcd" => ["345"]
  },
  "3.4.5.6" => {
    "abc" => [],
    "bcd" => ["456", "567"]
  }
}

在每个子哈希中保持相同的键,并使值全部为数组。处理整个散列的代码将更加直接和易于理解。

于 2012-08-16T15:09:39.917 回答