【问题标题】:add contents of 1 hash into another将 1 个哈希的内容添加到另一个
【发布时间】:2018-12-20 19:49:57
【问题描述】:

我有一个更改的父散列,我想确保子散列接受这些更改,但也保留他们以前拥有的密钥并且这些不应该丢失

这些是我拥有的示例哈希

one = {"endpoints"=>["get_route"], "features"=>["channel_selection"], "get_route"=>{"output"=>["total_length", "seca_length"], "options"=>["panama", "abcd"]}}

other = {"endpoints"=>["get_route"], "features"=>["channel_selection"], "get_route"=>{"output"=>["total_length", "seca_length"], "options"=>["panama", "suez", "kiel"]}}

我希望另一个哈希现在看起来像

other = {"endpoints"=>["get_route"], "features"=>["channel_selection"], "get_route"=>{"output"=>["total_length", "seca_length"], "options"=>["panama", "abcd", suez", "kiel"]}}

我尝试了以下代码,但它不起作用

result = propogate_changes(one, other)

def propogate_changes(one, other)
    one_keys = one.keys
    other_keys = other.keys
    combined = Hash.new
    unique_keys = one_keys.concat(other_keys).uniq

    unique_keys.each do |key|
        if(one[key].is_a?(Array)) then
            # if(other[key] == nil) then
            #     combined[key] = one[key]
            # else
                combined[key] = one[key].concat(other[key]).uniq
            # end
        else
            combined[key] = add_allowance(one[key], other[key])
        end
    end
    return combined
end

当一个键存在但另一个键缺失时,上述代码会失败

我也尝试了merge, deep_merge, reverse_merge,但它们都用一个哈希覆盖了我的另一个哈希,但它们都没有保留原始数据。

对此的任何建议将不胜感激

【问题讨论】:

  • How to merge Ruby hashes的可能重复
  • 目前还不清楚 - 哪个示例哈希是您称为“父”的哈希,哪个子哈希?另外,您想要的输出是什么样的?
  • 想用一个散列更新其他散列。我尝试了合并,deep_merge,但它们都覆盖了现有的散列,这不是我想要的。我想保留旧值并添加缺失值
  • 您可以使用 slice 方法从一个哈希中获取其他哈希中的键,并将其与其他类似,other.merge(one.slice(*other.keys)) 这是您的答案stackoverflow.com/a/6074412/5934752

标签: ruby-on-rails ruby ruby-on-rails-4


【解决方案1】:

试试这个自定义合并逻辑。

def find_missing_items_in_arr(arr1, arr2)
  arr1_size = arr1.size
  arr2_size = arr2.size

  if (arr1_size == arr2_size) && (arr1 & arr2).size == arr1_size
    return [] # Same array
  end

  arr2 - arr1
end

def custom_merge(target_hash, source_hash)
  # If you want to preserve frozen state of entries, please use `clone`
  duped_target_hash = target_hash.dup

  source_hash.each do |k, v|
    unless duped_target_hash.key?(k)
      duped_target_hash[k] = v
      next
    end

    case v
      when Array
        missing_items_in_arr = find_missing_items_in_arr(duped_target_hash[k], v)
        if missing_items_in_arr.size > 0
          duped_target_hash[k] += missing_items_in_arr
        end
      when Hash
        duped_target_hash[k] = custom_merge(duped_target_hash[k], v)
      else
        # Nothing to do here
    end
  end

  duped_target_hash
end

用法

one = {
  "endpoints"=>["get_route"],
  "features"=>["channel_selection"],
  "get_route"=> {
    "output"=> ["total_length", "seca_length"],
    "options"=> ["panama", "abcd"]
  }
}

other = {
  "endpoints"=>["get_route"],
  "features"=>["channel_selection"],
  "get_route"=> {
    "output"=> ["total_length", "seca_length"],
    "options"=> ["panama", "suez", "kiel"]
  }
}

rs_hash = custom_merge(other, one)

puts rs_hash

注意:Rails 提供了deep_merge,但这可以在 Rails 之外使用。我已经测试过,它会返回您想要的输出。它还处理更多嵌套条目,例如

one = {
  "endpoints"=>["get_route"],
  "features"=>["channel_selection"],
  "get_route"=> {
    "output"=> ["total_length", "seca_length"],
    "options"=> ["panama", "abcd"],

    "custom_options" => {
      "custom_output" => ["abc"],
      "custom_input" => ["xyz" ]
    }
  }
}

other = {
  "endpoints"=>["get_route"],
  "features"=>["channel_selection"],
  "get_route"=> {
    "output"=> ["total_length", "seca_length"],
    "options"=> ["panama", "suez", "kiel"],

    "custom_options" => {
      "custom_output" => ["abc", "def"]
    }
  }
}

希望这会有所帮助。

【讨论】:

  • 非常感谢..让我开心
猜你喜欢
  • 2015-12-03
  • 2017-01-01
  • 2013-06-24
  • 2019-05-31
  • 2020-12-11
  • 2014-05-25
  • 1970-01-01
  • 2023-03-10
  • 2013-01-10
相关资源
最近更新 更多