2017-08-26 153 views
1

我看到几个职位对数组排序是哈希值的价值,但我想排序数组的数组,它是一个哈希值。 我有一个哈希,看起来像这样:排序数组,它是一个哈希

h = { 
     "pets"=>[["dog", 1], ["cat", 2]], 
     "fruits"=>[["orange", 1], ["apple", 2]] 
    } 

我想根据内的阵列的第一元件(串)进行排序数组的数组。 所以我希望得到的结果是

{ 
    "pets"=>[["cat", 2], ["dog", 1]], 
    "fruits"=>[["apple", 2], ["orange", 1]] 
} 

这就是我现在所拥有的:

h.map do |key, value| 
    value.sort_by! { |x, y| x[0] <=> y[0] } 
end 

但这只是返回原始数组。我需要改变什么? 谢谢!

回答

1

的一个问题,我看到的是,你正试图map您的哈希值。这将始终返回一个数组。

在这种情况下,你会得到这样的事情: [[["cat", 2], ["dog", 1]], [["apple", 2], ["orange", 1]]]

如果要修改到位的哈希值,你可以这样做:

h.each { |key, value| h[key] = value.sort_by { ... } } 

然后h将是新的散列,按照您的期望排序。 或者你可以将其设置为另一个变量:

new_hash = h.each { |key, value| value.sort_by! { ... } } 

下,它看起来像你混淆sortsort_by。 (很容易做到) 当您使用sort,你通过这两个变量在块分配给被比较的值。 (在你的情况下,数组["dog", 1]是一个参数,而另一个将是另一个数组来比较它,就像["cat", 2]) 然而,sort_by希望你做的计算,以确定它的位置是在新的秩序。通常,sort_by只接受一个参数,但因为您正在处理数组(并且因为Ruby处理元组的方式),所以当您告诉sort_by接受2个参数(xy)时,它们将设置为您的第一个和第二个值阵列。 (x == "dog"y == 1

所以,你来到这里2种选择:保持你的块相同,切换你的枚举法sort,或者切换到sort_by和更改块:

sort

h.each { |key, value| h[key] = value.sort! { |x, y| x[0] <=> y[0] } } 

sort_by

h.each { |key, value| h[key] = value.sort_by! { |x, y| y } } # In this case, `y` is the second value in your arrays, which is the integer 
+1

就叫''通过散列#map'回到获得哈希回阵列上to_h'。 – mudasobwa

3
h.merge(h) { |*, n| n.sort } 
    #=> {"pets"=>[["cat", 2], ["dog", 1]], "fruits"=>[["apple", 2], ["orange", 1]]} 

这不修改h

这使用Hash#merge的形式,它使用一个块来确定两个散列中正在合并的键的值,这里是所有键。该块有三个块变量,公共密钥k,k的值为“旧散列”,o,“新”散列值为kn(这里on当然是相等的。)I'米只使用最后这些变量的,所以我已经表达了块变量为|*, n|,而不是|k, o, n|详见文档

不发生变异h另一种方法:。

h.each_key.zip(h.each_value.map(&:sort)).to_h 
    #=> {"pets"=>[["cat", 2], ["dog", 1]], "fruits"=>[["apple", 2], ["orange", 1]]} 

这可以改为写成

h.keys.zip(h.values.map(&:sort)).to_h 
+1

杰出的合并使用,Cary。谢谢,我真的很高兴看到这一点。在后面的例子中'h [k] .sort!'应该足够了。 – mudasobwa

+0

@mudasobwa,很好的建议。我做了改变。 –

+0

minor nitpick,可以使用'each_key'而不是'keys.each',可能只是一个样式首选项,但它是一个东西,因为你正在排序,所以还有'each_value' –

3

不可改变的版本,无副作用:

h.map { |k, v| [k, v.sort_by(&:first)] }.to_h