Ruby 将数组转换为散列的键

Ruby 将数组转换为散列的键,ruby,arrays,hash,Ruby,Arrays,Hash,如何将数组转换为值为0的散列,而不使用每个循环 例如,给定此数组: [1, 2, 3, 4] 我想得到这个散列: {"1"=>0, "2"=>0, "3"=>0, "4"=>0} 或者以更干净的方式(感谢,请参见评论中的讨论) 标准方法是: 或者Enumerable#mash如果您碰巧使用了facet。我想不出比这更简洁、更具说明性的东西了: xs.mash { |x| [x.to_s, 0] } 我是simple的粉丝,我永远记不清事情有多疯狂#inject或Ha

如何将数组转换为值为
0
的散列,而不使用
每个循环

例如,给定此数组:

[1, 2, 3, 4]
我想得到这个散列:

{"1"=>0, "2"=>0, "3"=>0, "4"=>0}
或者以更干净的方式(感谢,请参见评论中的讨论)

标准方法是:

或者
Enumerable#mash
如果您碰巧使用了facet。我想不出比这更简洁、更具说明性的东西了:

xs.mash { |x| [x.to_s, 0] }

我是simple的粉丝,我永远记不清事情有多疯狂
#inject
或Hash构造函数参数是如何工作的

array = [1, 2, 3, 4]
hash = {}

array.each do |obj|
  hash[obj.to_s] = 0
end

puts hash.inspect # {"1"=>0, "2"=>0, "3"=>0, "4"=>0}

好的,事实上,我会使用
每个带有对象的\u
,但是发布这个,因为它更有趣

ary = *1..4

hash = Hash[ary.zip ary.dup.fill 0]

hash # => {1=>0, 2=>0, 3=>0, 4=>0}

a.each_with_object({}{e,a|a[e.to_s]=0}
可能是一个更好的选择,因为你不是真的在注射。@mu:为什么不注射?它看起来是一个标准的折叠,只是它确实可以用块中的单个表达式来编写:
array.inject({}){acc,x{acc.update(x.to_s=>0)}
(使用update提高效率,纯函数将是一个合并)@tokland:the
;a
是使用
inject
的臭味部分,通过来自块的“虚拟”返回值强制反馈,因此块的结构是{做我真正想做的事;哦{是的}这是{u inject\u so\u return\u}
。因此
inject`更像是一个通用迭代器,而不是注入。我可能会选择acc.merge!(x.to_s=>0)
(出于同样的原因,如果我想使用
inject
,您会使用
update
)。也许我对这种形式的
inject
的问题是,你必须看两遍,以确保块的返回值是正确的。顺便说一句,其中一个是我的,所以请阅读我的第一条评论,作为建议而不是批评。@Andrew:
inject
reduce
是完全等效的,正如你所知,
inject
只是一个来自Smalltalk传统的“有趣”名字。关于“等维”问题,我认为你看错了。这里,
inject
获取一个项目列表(一个数组)以返回一个累积值(一个散列),其初始值为该累积类型(一个散列),这正是折叠的含义。用哈斯克尔的话来说:
[a]#inject::b->(b->a->b)->b
。这些类型保存在代码段中。这种方法的问题是:Ruby有
Hash[…]
(就像Python有
dict
),所以没有必要这样做。我感谢大家的回答,但我最喜欢这个答案。谢谢@TonyHassan很有趣,你接受了这一点,尽管你明确要求不使用
每一个
“简单”是一个主观概念,所以我不会去那里。但是没有充分利用编程语言的能力,这是我无法理解的。为什么要写四行而一行完全惯用的行就可以了?诚然,对于一个有命令式背景(或没有背景)的新手来说,这更容易理解,但在某个时刻,Ruby程序员必须学习一些函数原理。但我一看到它就改变了主意。我尽量保持灵活性。:)为什么不使用每个
的约束?
xs.mash { |x| [x.to_s, 0] }
array = [1, 2, 3, 4]
hash = {}

array.each do |obj|
  hash[obj.to_s] = 0
end

puts hash.inspect # {"1"=>0, "2"=>0, "3"=>0, "4"=>0}
ary = *1..4

hash = Hash[ary.zip ary.dup.fill 0]

hash # => {1=>0, 2=>0, 3=>0, 4=>0}