Ruby中的数组哈希

13

我有一个哈希表,其中键是字符串,值是字符串数组。

我想要类似于这样的东西:

{"k1"=>["v1", "v2"], "k2"=>["v3", "v4"]} 

我只有一个哈希表和一个数组来实现这个功能。我编写了以下代码:

hash1 = Hash.new
arr = Array.new
arr.push "v1"
arr.push "v2"
hash1["k1"] = arr 

#hash is like this: {"k1"=>["v1", "v2"]
#Now I clear the array to read the new values

arr. clear
arr.push "v3"
arr.push "v4"
hash1["k2"] = arr
puts hash1

#Output: {"k1"=>["v3", "v4"], "k2"=>["v3", "v4"]}
#Notice that k1's value also got updated

然后我改了一行代码:

hash1 = Hash.new
arr = Array.new
arr.push "v1"
arr.push "v2"
hash1["k1"] = arr 

arr = [] # ** This is the only changed line.  Now k1's value is correct. **
arr.push "v3"
arr.push "v4"
hash1["k2"] = arr
puts hash1
#Output: {"k1"=>["v1", "v2"], "k2"=>["v3", "v4"]} (which I wanted)

有人可以向我解释一下这是如何发生的吗?我对Ruby非常陌生。理想情况下,解决这个问题的正确方法是什么?


2
我只有一个哈希表和一个数组来实现这个功能。在你的第二个例子中,你有两个数组。 - Ajedi32
2
{ }Hash.new 更常用,[ ]Array.new 更常用。 - tadman
@tadman,为什么这样更好呢?只是为了可读性吗?还是有其他好处? - Anirudhan J
1
@AnirudhanJ 这种表示法更简洁,出错的可能性也更小。它还可以轻松地添加元素,其中 { } 变成了 { foo: 'bar' },而不必从 Hash.new 切换到那个表示法。 - tadman
2个回答

14

这应该向您展示正在发生的事情(object_id是您的朋友)。 (我在Object_id中插入了一个下划线,以便更容易看到差异。)

hash1 = {}            # => {} 
arr = ["v1", "v2"]    # => ["v1", "v2"] 
arr.object_id         # => 7016637_4343580 
hash1["k1"] = arr     # => ["v1", "v2"] 
hash1                 # => {"k1"=>["v1", "v2"]}
hash1["k1"].object_id # => 7016637_4343580 
arr.clear             # => [] 
arr.object_id         # => 7016637_4343580 
arr << "v3" << "v4"   # => ["v3", "v4"] 
arr.object_id         # => 7016637_4343580 
hash1["k2"] = arr     # => ["v3", "v4"] 
hash1                 # => {"k1"=>["v3", "v4"], "k2"=>["v3", "v4"]} 
hash1["k1"].object_id # => 7016637_4343580 
hash1["k2"].object_id # => 7016637_4166580 

arr = []              # => [] 
arr.object_id         # => 7016637_4036500 
arr = ["v5", "v6"]    # => ["v5", "v6"] 
arr.object_id         # => 7016637_3989880 
hash1                 # => {"k1"=>["v3", "v4"], "k2"=>["v3", "v4"]} 
hash1["k1"].object_id # => 7016637_4343580 
hash1["k2"] = arr     # => ["v5", "v6"] 
hash1                 # => {"k1"=>["v3", "v4"], "k2"=>["v5", "v6"]} 
hash1["k1"].object_id # => 7016637_4343580 
hash1["k2"].object_id # => 7016637_3989880 

很好的解释。如果我想按值v1或v2对我的哈希进行排序,应该如何操作?hash1.sort_by {|k,v| v.first} #未定义方法'[]'用于nil:NilClasshash1.sort_by {|k,v| v[0]} #未定义方法'[]'用于nil:NilClass - Aparichith
我不太明白你的问题。请留下另一个评论,其中包含hash1的示例以及您希望哈希的结果。 - Cary Swoveland
考虑这样的哈希数组: [{"a"=>[576, 236]}, {"z"=>[348, 4859]}, {"b"=>[174, 98]}, {"t"=>[165, 145]}, {"u"=>[97, 184]}, {"m"=>[595, 374]}, {"g"=>[61, 86]}]如何根据每个键的值之和对数组进行排序?如下所示: [{"z"=>[348, 4859]}, {"a"=>[576, 236]}, {"m"=>[595, 374]}, {"t"=>[165, 145]}, {"u"=>[97, 184]}, {"b"=>[174, 98]}, {"g"=>[61, 86]}] - Aparichith
1
@h.APP.y 用于首先按最大总和排序:arr.sort_by { |h| -h.values.first.reduce(:+) } - Cary Swoveland
感谢您的指导。 您能再详细解释一下吗?我想知道它是如何工作的。谢谢。 - Aparichith
我已经私下提供了所请求的解释。 - Cary Swoveland

3

你在哈希表中保存的数组仍然被称为arr,因此清空它并使用arr.push将清除并添加新值到哈希表中保存的数组。但是,如果执行arr = []arr现在将引用一个与哈希表中保存的不同的新数组。

你可以通过以下方式向哈希表中简单地添加新数组:

hash1["k2"] = ["v3", "v4"]

或者

hash1["k2"] = %w[v3 v4]

2
为了让您看到它的工作原理,可以在您的arrarr.object_id上执行此操作,您将收到一个数字。当您使用clear并再次检查ID时,它仍然是相同的(仍然是相同的引用)。当您arr = []时,您将创建一个具有相同名称的新对象,覆盖旧对象,并使用arr.object_id进行检查,您将获得不同的ID号码,这意味着一个新对象 :) - user745235

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