【问题标题】:Ruby list values are identical after assigning different values分配不同的值后,Ruby 列表值相同
【发布时间】:2013-07-09 03:17:33
【问题描述】:

抱歉标题混乱,不知道如何描述这个问题。

在 Ruby on Rails 控制器中,我创建了一个名为 @commits 的列表,其中 @commits 中的每个项目都应包含一个哈希表,其元素是每个提交的各种属性的值。这些属性值存储在 Redis 数据库中。

下面,我遍历了一个属性列表,这些属性的值应该从 Redis 中获取,然后为 8 个不同的提交中的每一个获取这些值。然后,我将 redis 中的值放入每个提交的不同哈希表中,使用提交属性名称作为哈希的键。

# Initialize @commits as a list of eight empty hash tables
@commits = Array.new(8, {})

# Iterate over the attributes that need hashed for each item in @commits
[:username, :comment, :rev, :repo].each do |attrib|
    # 8 items in @commits
    8.times do |i| 
       # Get a value from redis and store it in @commits[i]'s hash table
       @commits[i][attrib] = $redis.lindex(attrib, i)

       # Print the value stored in the hash
       # Outputs 7, 6, .., 0 for @commits[i][:rev]
       puts @commits[i][attrib].to_s
    end
end

# Print the value of every item that was stored in the hash tables above, 
# but only for the :rev key
# Outputs 0 eight times
8.times do |i|
    puts @commits[i][:rev]
end

但是,根据上面的 cmets,@commits[0..7] 的哈希值似乎都相同,尽管它们在上面几行似乎被正确存储。以哈希键:rev为例,第一个puts输出7..0是正确的,但是第二个puts输出了8次数字0。

有人知道为什么吗?

【问题讨论】:

  • 使用像$redis 这样的全局变量可能是糟糕设计的标志。真的有必要吗?
  • 这不是必需的,而且它肯定是糟糕的设计,但这是我正在试验的一次性项目。我不会在生产中这样做。
  • 你能说明@commits 在这些块之前是如何被初始化/创建的吗?
  • 糟糕,本来就是这样。我已对其进行了编辑。
  • 我知道你在做类似的事情。我添加了一个解释这个微妙错误的答案。

标签: ruby-on-rails ruby redis


【解决方案1】:

如果您展示如何初始化 @commits 会有所帮助,但看起来您已经创建了一个包含多个对同一对象的引用的结构。

不正确,为所有键回收了相同的对象:

@commits = Hash.new([ ])

正确,为每个键创建新对象:

@commits = Hash.new { |h, k| h[k] = [ ] }

你可能会犯同样的错误:

@commits = Array.new(8, [ ])

这将导致以下行为:

a = Array.new(4, [ ])
a[0]
# => []
a[0] << 'x'
# => ["x"]
a
# => [["x"], ["x"], ["x"], ["x"]]

可以通过传入一个块来修复:

a = Array.new(4) { [ ] }
a[0]
# => []
a[0] << 'x'
# => ["x"]
a
# => [["x"], [], [], []]

但是,看到一个用值预初始化的数组是非常不寻常的。通常这些只是延迟初始化,或者使用 Hash 代替 Array。

【讨论】:

  • 我认为您只是错过了@commits = Array.new(8, {}) 更新,不过猜对了。
  • 是的,你一针见血。我误解了 Array.new 函数如何初始化数组。测试并确认您的建议解决了我的问题。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-20
  • 1970-01-01
相关资源
最近更新 更多