从两个不同大小的数组创建一个Hash,并迭代直到没有一个键为空



有两个不同大小的数组,我想把longer数组作为键,把shorter数组作为值。然而,我不希望任何键保持空,所以这就是为什么我需要继续迭代shorter数组,直到所有键都有一个值。

EDIT:我想保持数组更长完整,但没有空值,这意味着保持迭代更短,直到所有键都有一个值。

longer  = [1, 2, 3, 4, 5, 6, 7]
shorter = ['a', 'b', 'c']
Hash[longer.zip(shorter)]
#=> {1=>"a", 2=>"b", 3=>"c", 4=>nil, 5=>nil, 6=>nil, 7=>nil}

预期结果

#=> {1=>"a", 2=>"b", 3=>"c", 4=>"a", 5=>"b", 6=>"c", 7=>"a"}

这是一个优雅的例子。你可以"循环"短数组

longer  = [1, 2, 3, 4, 5, 6, 7]
shorter = ['a', 'b', 'c']
longer.zip(shorter.cycle).to_h # => {1=>"a", 2=>"b", 3=>"c", 4=>"a", 5=>"b", 6=>"c", 7=>"a"}

一种粗糙的方式,直到你发现更优雅的方式:根据较短数组的长度对较长数组进行切片,并对其进行迭代以重新映射值。

mapped = longer.each_slice(shorter.length).to_a.map do |slice|
           Hash[slice.zip(shorter)]
         end
=> [{1=>"a", 2=>"b", 3=>"c"}, {4=>"a", 5=>"b", 6=>"c"}, {7=>"a"}]

将映射数组中的所有哈希合并为一个哈希

final = mapped.reduce Hash.new, :merge
=> {1=>"a", 2=>"b", 3=>"c", 4=>"a", 5=>"b", 6=>"c", 7=>"a"}

这是一个有趣的答案。

longer  = [1, 2, 3, 4, 5, 6, 7]
shorter = ['a', 'b', 'c']
h = Hash.new do |h,k|
  idx = longer.index(k)
  idx ? shorter[idx % shorter.size] : nil
end
  #=> {}
h[1] #=> a
h[2] #=> b
h[3] #=> c
h[4] #=> a
h[5] #=> b
h[6] #=> c
h[7] #=> a
h[8] #=> nil
h #=> {}
h.values_at(3,5) #=> ["c", "b"] 

如果这还不够好(例如,如果您希望使用Hash方法,如keys, key?, merge, to_a等),您可以很容易地创建相关的散列:

longer.each { |n| h[n] = h[n] }
h #=> {1=>"a", 2=>"b", 3=>"c", 4=>"a", 5=>"b", 6=>"c", 7=>"a"}  

最新更新