将哈希表中弹出的类对象分配到变量中

  • 本文关键字:对象 分配 变量 哈希表 ruby
  • 更新时间 :
  • 英文 :


我有一个我制作的类类型的2D哈希表。我正试图从哈希表中弹出一个值,并将其分配给一个变量:

foo = @bar[0].pop()

但是,foo中没有填充该对象。我已经确保@bar[0].pop实际上弹出了正确的对象,因为我的原始实现是在一个Class方法中,代码是:

@test.each {|x| return @bar[x].pop() if something == x }

并且该方法返回正确的对象。然而,我正在尝试在方法中执行更多的操作,这需要我将弹出的对象保存在一个变量中,我不确定如何通过赋值或我的语法是否不正确来做到这一点。

编辑:这是我的实际代码(相关内容(

class Candy
attr_accessor :name, :shelved
def initialize
@name = ""
@shelved = 0
end
end
class Shelf
attr_accessor :candy_hash, :total_candies, :shelf_full, :num_candies,
:name_array
def initialize()
@candy_hash = Hash.new{ |h, k| h[k] = []}
@total_candies = 0
@shelf_full = 0
@name_array = Array.new
end
end
class Shop
attr_accessor :shelves, :unshelved_hash, :unshelved_names
def initialize
@shelves = []
@unshelved_hash = Hash.new{ |h, k| h[k] = []}
@unshelved_names = []
end

def push_new_unshelved(candy)
@unshelved_names << candy.name
@unshelved_hash[@unshelved_names.last].push(candy)
end
def push_existing_unshelved(candy)
@unshelved_names.each{|x| @unshelved_hash[x].push(candy) && break if x == candy.name}
end
def receive_candy(candy)
check = self.check_if_exists(candy)
if check == 0
self.push_new_unshelved(candy)
else
self.push_existing_unshelved(candy)
end
end
def get_hash_key(candy_name)
@unshelved_names.each{|x| return x if candy_name == x}
end

def get_unshelved_candy(candy_name)
candy = @unshelved_hash[self.get_hash_key(candy_name)].pop()
return candy 
# problem is here, candy is never populated 
# I'm gonna do more in this method but this is the important part
# working solution right now: return @unshelved_hash[self.get_hash_key(candy_name)].pop()
end
def shelve_single(candy_name)
candy = self.get_unshelved_candy(candy_name)
@shelves[self.find_empty_shelf].add_candy(candy)
end
end
shop1.receive_candy(Candy.new("snickers"))
shop1.shelve_single("snickers")

foo没有用对象填充。

对局部变量的赋值不能静默失败。foo = @bar[0].pop()将结果从@bar[0].pop()分配给foo。(或在@bar[0].pop()失败时引发异常(

如果通过";没有被填充">你的意思是nil的值,那是因为@bar[0].pop()返回了nil。这很可能是因为@bar[0]是一个空数组。(也许是因为它一开始没有被填充(

这是我的实际代码(相关的东西(

乍一看,您的代码似乎过于复杂。当使用基于默认值的散列(如@candy_hash = Hash.new { |h, k| h[k] = [] }(时,您可以简单地通过它们的密钥访问底层数组,例如@candy_hash["snickers"]。由于散列会根据需要自动创建一个空数组,因此无需检查它是否存在。你可以只push元素:

candies = Hash.new { |h, k| h[k] = [] }
candies["snickers"].push(Candy.new("snickers"))
candies["snickers"].push(Candy.new("snickers"))
candies["kit kat"].push(Candy.new("kit kat"))
candies
#=> {
#     "snickers"=>[
#       #<Candy:0x00007fad03046818 @name="snickers">,
#       #<Candy:0x00007fad030467c8 @name="snickers">
#     ],
#     "kit kat"=>[
#       #<Candy:0x00007f981303a658 @name="kit kat">
#     ]
#   }
candies.pop("snickers")
#=> #<Candy:0x00007fad030467c8 @name="snickers">

为了获得糖果名称,您可以简单地检查散列的密钥:(而不是维护一个单独的数组(

candies.keys
#=> ["snickers", "kit kat"]

关于您的问题,让我们从使用CandyShelf的不完整但有效的测试实现开始:

class Candy
attr_reader :name
def initialize(name)
@name = name
end
end
class Shelf
attr_reader :candy_hash
def initialize
@candy_hash = Hash.new { |h, k| h[k] = [] }
end
def add_candy(candy)
candy_hash[candy.name].push(candy)
end
def remove_candy(candy_name)
candy_hash[candy_name].pop
end
end

基于此,我们可以实现Shop如下:

class Shop
attr_reader :shelves, :unshelved_hash
def initialize
@shelves = []
@unshelved_hash = Hash.new { |h, k| h[k] = [] }
end
def receive_candy(candy)
@unshelved_hash[candy.name].push(candy)
end
def get_unshelved_candy(candy_name)
@unshelved_hash[candy_name].pop
end
def find_empty_shelf
@shelves.first # replace with actual logic
end
def shelve_single(candy_name)
candy = get_unshelved_candy(candy_name)
empty_shelf = find_empty_shelf
empty_shelf.add_candy(candy)
end
end

示例:(我省略了对象ID(

shop = Shop.new
shop.shelves << Shelf.new
shop.receive_candy(Candy.new("snickers"))
shop.unshelved_hash #=> {"snickers"=>[#<Candy @name="snickers">]}
shop.shelves        #=> [#<Shelf @candy_hash={}>]
shop.shelve_single("snickers")
shop.unshelved_hash #=> {"snickers"=>[]}
shop.shelves        #=> [#<Shelf @candy_hash={"snickers"=>[#<Candy @name="snickers">]}>]

您也可以用Shelf的实例替换unshelved_hash,以便重用其代码:

class Shop
attr_reader :shelves, :unshelved
def initialize
@shelves = []
@unshelved = Shelf.new
end
def receive_candy(candy)
@unshelved.add_candy(candy)
end
def get_unshelved_candy(candy_name)
@unshelved.remove_candy(candy_name)
end
# ...
end

上面的Shop实现还不完整,但它们应该让您开始。

延迟分配值的散列的一个常见缺陷是它们不能自动处理删除。您可能已经注意到,在搁置我们的测试士力架后,unshelved_hash仍然包含"snickers"=>[]。要完全删除它,您可以在pop关闭数组的最后一项:之后delete相应的密钥

def remove_candy(candy_name)
candy = candy_hash[candy_name].pop
candy_hash.delete(candy_name) if candy_hash[candy_name].empty?
candy
end

注意:这个答案是基于一些假设来填补问题中的空白。

如果要将值分配给方法中的变量,则需要使用break而不是returnreturn退出整个方法,而break只中断当前迭代器(在您的情况下为each(:

def my_method
my_value = @test.each {|x| break @bar[x].pop() if something == x }
...
end

最新更新