我有一个数组,我想创建一个哈希,其键是数组的元素,其值是(数组)数组的索引。我希望得到类似的东西:
array = [1,3,4,5]
... # => {1=>0, 3=>1, 4=>2, 5=>3}
array = [1,3,4,5,6,6,6]
... # => {1=>0, 3=>1, 4=>2, 5=>3, 6=>[4,5,6]}
此代码:
hash = Hash.new 0
array.each_with_index do |x, y|
hash[x] = y
end
只有在我没有重复元素的情况下才能正常工作。当我有重复的元素时,它不会。
我对如何得到这样的东西有任何想法吗?
答案 0 :(得分:3)
您可以将逻辑更改为特殊情况,当密钥已存在时,将其转换为数组并推送新索引:
arr = %i{a a b a c}
result = arr.each.with_object({}).with_index do |(elem, memo), idx|
memo[elem] = memo.key?(elem) ? [*memo[elem], idx] : idx
end
puts result
# => {:a=>[0, 1, 3], :b=>2, :c=>4}
不过,值得一提的是,无论你在这里做什么,都可能以不同的方式完成......我们没有背景。一般来说,保持key-val数据类型一致是一个好主意,例如这里的值可以是数字或数组的事实是一些代码味道。
另请注意,在此处使用Hash.new(0)
是没有意义的,除非您有意设置默认值(没有理由这样做)。请改用{}
答案 1 :(得分:2)
我加了两分钱:
array = [1,3,4,5,6,6,6,8,8,8,9,7,7,7]
hash = {}
array.map.with_index {|val, idx| [val, idx]}.group_by(&:first).map do |k, v|
hash[k] = v[0][1] if v.size == 1
hash[k] = v.map(&:last) if v.size > 1
end
p hash #=> {1=>0, 3=>1, 4=>2, 5=>3, 6=>[4, 5, 6], 8=>[7, 8, 9], 9=>10, 7=>[11, 12, 13]}
当然,它失败了,重复元素不相邻。
这是一步一步的扩展版本,以展示它的工作原理。
基本思想是构建一个具有值和索引对的临时数组,然后对其进行处理。
array = [1,3,4,5,6,6,6]
tmp_array = []
array.each_with_index do |val, idx|
tmp_array << [val, idx]
end
p tmp_array #=> [[1, 0], [3, 1], [4, 2], [5, 3], [6, 4], [6, 5], [6, 6]]
tmp_hash = tmp_array.group_by { |e| e[0] }
p tmp_hash #=> {1=>[[1, 0]], 3=>[[3, 1]], 4=>[[4, 2]], 5=>[[5, 3]], 6=>[[6, 4], [6, 5], [6, 6]]}
hash = {}
tmp_hash.map do |k, v|
hash[k] = v[0][0] if v.size == 1
hash[k] = v.map {|e| e[1]} if v.size > 1
end
p hash #=> {1=>1, 3=>3, 4=>4, 5=>5, 6=>[4, 5, 6]}
它可以写成一行:
hash = {}
array.map.with_index.group_by(&:first).map { |k, v| v.size == 1 ? hash[k] = v[0][1] : hash[k] = v.map(&:last) }
p hash
答案 2 :(得分:2)
如果您准备接受
@a = sort { $a <=> $b } @a
作为返回值,您可以写下以下内容。
{ 1=>[0], 3=>[1], 4=>[2], 5=>[3], 6=>[4,5,6] }
此计算的第一步如下。
array.each_with_index.group_by(&:first).transform_values { |v| v.map(&:last) }
#=> {1=>[0], 3=>[1], 4=>[2], 5=>[3], 6=>[4, 5, 6]}
这可以帮助读者遵循后续计算。
我认为你会发现这个返回值通常比问题中给出的更方便。
以下是几个例子,它们显然更适合所有值为数组。让:
array.each_with_index.group_by(&:first)
#=> {1=>[[1, 0]], 3=>[[3, 1]], 4=>[[4, 2]], 5=>[[5, 3]], 6=>[[6, 4], [6, 5], [6, 6]]}
创建一个哈希h_orig = { 1=>0, 3=>1, 4=>2, 5=>3, 6=>[4,5,6] }
h_mod { 1=>[0], 3=>[1], 4=>[2], 5=>[3], 6=>[4,5,6] }
,其键是h
的唯一元素,其值是键在数组中出现的次数
array
创建一个哈希h_mod.transform_values(&:count)
#=> {1=>1, 3=>1, 4=>1, 5=>1, 6=>3}
h_orig.transform_values { |v| v.is_a?(Array) ? v.count : 1 }
,其键是h
的唯一元素,其值等于数组中第一个元素实例的索引。
array
在这些示例中,给定h_mod.transform_values(&:min)
#=> {1=>0, 3=>1, 4=>2, 5=>3, 6=>4}
h_orig.transform_values { |v| v.is_a?(Array) ? v.min : v }
,我们可以将索引值转换为包含单个索引的数组。
h_orig
这几乎不能证明所有值都是数组通常更方便,但这是我的经验和许多其他人的经验。