当前位置 : 主页 > 编程语言 > ruby >

基于Ruby的类似位置合并数组的哈希值

来源:互联网 收集:自由互联 发布时间:2021-06-23
我有以下两个哈希与数组作为值. a = { "Us" = [["1", ["1", "2"]], ["2", ["1"]]], "Pa" = [["1", ["1", "3", "5"]], ["4", ["7"]]]}b = { "Us" = [["1", ["F", "O"]], ["2", ["N"]]], "Pa" = [["1", ["S", "D", "H"]], ["4", ["K"]]]} 我正在
我有以下两个哈希与数组作为值.

a = {
  "Us" => [["1", ["1", "2"]], ["2", ["1"]]],
  "Pa" => [["1", ["1", "3", "5"]], ["4", ["7"]]]
}
b = {
  "Us" => [["1", ["F", "O"]], ["2", ["N"]]],
  "Pa" => [["1", ["S", "D", "H"]], ["4", ["K"]]]
}

我正在尝试合并哈希以得到一个像这样的决赛:

c = {
  "Us" => [["1", ["1|F", "2|O"]], ["2", ["1|N"]]],
  "Pa" => [["1", ["1|S", "3|D", "5|H"]], ["4", ["7|K"]]]
}

我发现以下代码与merge,并试图将它应用于我的问题,但我收到一个错误:

a.merge(b) {|key, a_val, b_val| a_val.merge b_val }
# >> NoMethodError: undefined method `merge' for [["1", ["1", "2"]], ["2", ["1"]]]:Array

我甚至弄错了b:

a + b
# >> NoMethodError: undefined method `+' for #<Hash:0x0000060078e460>

<<<<更新>>>>

谢谢Cary和tadman.在原始问题之外,我显示了我的输入文件和我尝试获取的输出.我展示的是为了让你知道为什么
我以这种方式生成了2个哈希.在输出中,我创建了块,其中父亲是第1列的唯一值,在子节点下面(第2列中与col 1相关的唯一值).
第3列是属于col2中的值的子子,第4列是与col3相关的文本内容.

可能哈希“c”从一开始就更容易生成.

这是我的输入文件

Main,Stage1,Stage2,Description
Us,1,1,F
Us,1,2,O
Us,2,1,N
Pa,1,1,S
Pa,1,3,D
Pa,1,5,H
Pa,4,7,K

这是我几乎得到的输出.

Main..Stage1..Stage2..Description       
Us      
......1
..............1.......F
..............2.......O
......2 
..............1.......N
Pa
......1
..............1.......S
..............3.......D
..............5.......H
......4
..............7.......K

然后我就能够创建这个代码了,但是像tadman所说的那样,我需要重新排序我的方式以使事情变得更容易,因为
我用了4个哈希.在我创建哈希“a”和“b”后,我被卡住了,因为我需要一个唯一的哈希来迭代并且能够在上面显示的输出结构中打印.

在发布问题之前我的代码

X = Hash.new{|hsh,key| hsh[key] = [] }
Y = Hash.new{|hsh,key| hsh[key] = [] }
a = Hash.new{|hsh,key| hsh[key] = [] }
b = Hash.new{|hsh,key| hsh[key] = [] }

File.foreach('file.txt').with_index do
    |line, line_num|

    if line_num > 0
        r = line.split(",")

        X[r[0] + "°" + r[1]].push r[2]
        Y[r[0] + "°" + r[1]].push r[3].strip
    end
end

X.each{ |k,v|
    lbs = k.split("°")
    a[lbs[0]].push [ lbs[1], v] #Here I generate hash a
}

Y.each{ |k,v|
    lbs = k.split("°")
    b[lbs[0]].push [ lbs[1], v] #Here I generate hash b
}
由于所有复杂的嵌套,你在这里需要一些工作来解决.如果你做了一些工作来重新排序数据的存储方式,这将会容易得多.

但你可以这样做:

a={"Us"=>[["1", ["1", "2"]], ["2", ["1"]]], "Pa"=>[["1", ["1", "3", "5"]], ["4", ["7"]]]}
b={"Us"=>[["1", ["F", "O"]], ["2", ["N"]]], "Pa"=>[["1", ["S", "D", "H"]], ["4", ["K"]]]}

c = a.keys.map do |k|
  ah = a[k].to_h
  bh = b[k].to_h

  [
    k,
    ah.keys.map do |ka|
      [
        ka,
        ah[ka].zip(bh[ka]).map do |pair|
          pair.join('|')
        end
      ]
    end
  ]
end.to_h

# => {"Us"=>[["1", ["1|F", "2|O"]], ["2", ["1|N"]]], "Pa"=>[["1", ["1|S", "3|D", "5|H"]], ["4", ["7|K"]]]}

这里的关键是严格使用map来转换每一层和zip,将两个数组“拉链”成两对,然后可以将它们组合成所需的字符串目标.最后回到带有to_h的Hash,你得到你想要的东西.

每个子集都有一个中间转换为散列,以处理无序情况,其中可以指定不同序列中的明显“键”.

你想要做的是将它包装在一个带有描述性名称的方法中:

def hash_compactor(a,b)
  # ... (code) ...
end

这将有助于保持模块化.通常我尝试创建处理N个参数的解决方案,方法是将其定义为:

def hash_compactor(*input)
  # ...
end

输入是你给出的形式的各种集合的数组.结果代码令人惊讶地复杂得多.

请注意,这使得很多关于输入完全匹配的假设如果不是这样的话会爆炸.

网友评论