将哈希值添加至数组

3
我在这个练习中遇到了一点问题,你能帮我吗?我试图编辑一个脚本,但每次创建新实例时,最后一个元素都会覆盖其他元素(即)。
该类必须提供连续块的组合功能:即它必须能够从前一个块继承未明确定义为当前块的指令。
blocks = [] 

blocks << Block.new({ X:0, Y:100, Z:20}) # p blocks:({ X:0, Y:100, Z:20}) 

blocks << Block.new({X:100}, blocks[-1]) #p blocks:({ X:100, Y:100, Z:20},{ X:100, Y:100, Z:20})

blocks << Block.new({Y:0}, blocks[-1]) #p blocks:({ X:100, Y:0, Z:20},{ X:100, Y:0, Z:20},{ X:100, Y:0, Z:20})

我有问题的代码如下:

#!/usr/bin/env ruby

    class Block


      $instance_2 = true
      $instance_3 = true


      attr_reader :out


      def initialize(out, previous = nil )

        @out = update(out, previous)
      end # end initialize


      def update(actual, previous)
        puts "IN UPDATE: box is: #{previous}"
        box = previous
        if box != nil      
          puts "IF: changing is: #{actual}"
          actual.each do |key, value|
            box[key] = value               
          end  
           box  
        else
          puts "ELSE"
             actual   
        end # end if 
      end # end update

      def inspect
        @out
      end



    end # end Block

    blocks = []
    puts "\n#----------------------1 INSTANCE----------------------#" 
    blocks << Block.new({G: "00", X: 100, Y:100, Z: 100})
    puts "\n#----------------------blocks element----------------------#" 
    p blocks
    puts "last block is: #{blocks[-1].out}"

    puts "\n#----------------------2 INSTANCE----------------------#"  if $instance_2
    blocks << Block.new({G: "01"}, blocks[-1].out) if $instance_2 
    puts "\n#----------------------blocks element----------------------#"if $instance_2 
    p blocks if $instance_2
    puts "last block is: #{blocks[-1].out}"


    puts "\n#----------------------3 INSTANCE----------------------#" if $instance_3
    blocks << Block.new({G: "02"}, blocks[-1].out) if $instance_3 
    puts "\n#----------------------blocks element----------------------#" if $instance_3
    p blocks if $instance_3
    puts "last block is: #{blocks[-1].out}"

    puts "\n#----------------------4 INSTANCE----------------------#" if $instance_3
    blocks << Block.new({G: "03"}, blocks[-1].out) if $instance_3 
    puts "\n#----------------------blocks element----------------------#" if $instance_3
    p blocks if $instance_3
    puts "last block is: #{blocks[-1].out}"

嗯...看起来有人在进行制造自动化的练习,对吧?对于读者来说,Block类是一个G代码语句。 - Matteo Ragni
嗨Matteo,这是一个3D打印课程的练习,我们需要实现G代码。 你有什么解决我的问题的想法吗? - luca
请问您能否更好地解释一下您的代码存在什么问题以及您尝试了哪些方法?因为您的问题描述不够清晰。 - Matteo Ragni
我修改了这个问题,这是我的尝试,但是对于我创建的每个实例,哈希表的最后一个值都会覆盖之前所有的元素。如果您有时间,请试一下。非常感谢您的帮助。 - luca
Ciao Luca,我在我的答案中添加了一个部分,解释了你代码的问题所在... - Matteo Ragni
1个回答

2

这个问题不是很明确,但如果我理解正确的话,可以提供一个类,可能会或可能不会接受先前的块。你觉得这样的做法怎么样?

#!/usr/bin/env ruby

class Block < Hash

  def initialize(h, b=nil)
    [:x, :y, :z].each do |s|
      # We start by trying to assign the coordinate that is in the 
      # input hash
      if h[s]
        self[s] = h[s]
      else
      # If the coordinate is not in h, we check for it in b, but we have to
      # remember that if the block that we are providing in b does not have
      # the method :[] or the coordinate is nil we may raise an exception
        begin
          self[s] = b[s]
          raise if not self[s]
        rescue
          raise(Exception, "Cannot initialize block.")   
        end  
      end
    end 
  end

  def inspect
    "block:(x: #{self[:x]}, y: #{self[:y]}, z: #{self[:z]}"
  end
end

# Let's try it!
blocks = [] 
blocks << Block.new({ x:0, y:100, z:20}) 
puts blocks
puts
blocks << Block.new({x:100}, blocks[-1]) 
puts blocks
puts
blocks << Block.new({y:0}, blocks[-1])
puts blocks
puts

关于你的代码

让我们只考虑更新方法:

def update(actual, previous)
    puts "IN UPDATE: box is: #{previous}"
    box = previous                 # ! ! ! ! ! ! ! ! WHOOPS!
    if box != nil      
      puts "IF: changing is: #{actual}"
      actual.each do |key, value|
        box[key] = value               
      end  
       box  
    else
      puts "ELSE"
         actual   
    end # end if 
  end # end update

“哎呀”这一行是导致问题的原因。通过这一行,你将previous(实际上是一个对象变量引用)的引用赋值给了box变量。当你对box执行某些操作时,实际上是修改了两个变量所指向的内容。

你可以立即测试我所说的话。试着按照以下方式修改那一行:

box = previous.clone if previous

(nil没有#clone方法,这就是if背后的原理)。如果您再次运行它,您将获得未被修改的块列表。尽管如此,这不是有效的代码,您应该重新思考update方法的代码。


哇,它完全按照我的要求工作。我在我的代码中犯了很多错误:(非常感谢你的时间,朋友。 - luca
你正在尝试并且理解自己犯了哪些错误,这是一件好事。在这种情况下,这是一个很好的学习方式。继续努力。 - Matteo Ragni

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接