代码之家  ›  专栏  ›  技术社区  ›  Dhaval Chheda

将1哈希的内容添加到另一哈希中

  •  1
  • Dhaval Chheda  · 技术社区  · 6 年前

    我有一个父散列,它会发生变化,我想确保子散列接受这些变化,但同时保留以前的密钥,这些密钥不会丢失

    这些是我的样本

    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 但它们都用一个散列覆盖了我的另一个散列,但没有一个保留原始数据。

    如对此有任何建议,我们将不胜感激。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Jignesh Gohel    6 年前

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

    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 但这可以在铁轨外使用。我已经测试过了,它会返回你想要的输出。它还处理更多的嵌套条目,如

    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"]
        }
      }
    }
    

    希望这有帮助。