分配不同的值后,Ruby列表值是相同的

时间:2013-07-08 18:55:04

标签: ruby-on-rails ruby redis

很抱歉这个令人困惑的标题,不知道如何描述这个问题。

在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

但是,根据上面的评论,@ commit [0..7]似乎在哈希值中都有相同的值,尽管它们似乎正好存储在上面几行。以散列键:rev为例,第一个puts输出7..0,这是正确的,但第二个puts输出数字0八次。

任何人都知道为什么?

1 个答案:

答案 0 :(得分:5)

如果您展示如何初始化@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代替数组。