在Ruby中,将数组转换为哈希的最佳方法是什么

在Ruby中,将数组转换为哈希的最佳方法是什么,ruby,arrays,hashmap,Ruby,Arrays,Hashmap,在Ruby中,给定以下形式之一的数组 [apple, 1, banana, 2] [[apple, 1], [banana, 2]] …以…的形式将其转换为哈希的最佳方式是什么 {apple => 1, banana => 2} 只需使用Hash[*array\u variable.flant] 例如: a1 = ['apple', 1, 'banana', 2] h1 = Hash[*a1.flatten(1)] puts "h1: #{h1.inspect}" a2 = [

在Ruby中,给定以下形式之一的数组

[apple, 1, banana, 2]
[[apple, 1], [banana, 2]]
…以…的形式将其转换为哈希的最佳方式是什么

{apple => 1, banana => 2}

只需使用
Hash[*array\u variable.flant]

例如:

a1 = ['apple', 1, 'banana', 2]
h1 = Hash[*a1.flatten(1)]
puts "h1: #{h1.inspect}"

a2 = [['apple', 1], ['banana', 2]]
h2 = Hash[*a2.flatten(1)]
puts "h2: #{h2.inspect}"
使用
Array#flant(1)
限制递归,以便
Array
键和值按预期工作

编辑:看到我在写作时发布的回复,散列[a.flatten]似乎是一条出路。 在我仔细考虑回复时,文档中肯定遗漏了这一点。我认为如果需要的话,我写的解决方案可以作为替代方案

第二种形式更简单:

a = [[:apple, 1], [:banana, 2]]
h = a.inject({}) { |r, i| r[i.first] = i.last; r }
a=数组,h=散列,r=返回值散列(我们在其中累积的值),i=数组中的项

我能想到的做第一个表单的最整洁的方式是这样的:

a = [:apple, 1, :banana, 2]
h = {}
a.each_slice(2) { |i| h[i.first] = i.last }

不确定这是否是最好的方法,但这是有效的:

a = ["apple", 1, "banana", 2]
m1 = {}
for x in (a.length / 2).times
  m1[a[x*2]] = a[x*2 + 1]
end

b = [["apple", 1], ["banana", 2]]
m2 = {}
for x,y in b
  m2[x] = y
end

如果数值是seq索引,那么我们可以有更简单的方法。。。 这是我提交的代码,我的Ruby有点生锈了

   input = ["cat", 1, "dog", 2, "wombat", 3]
   hash = Hash.new
   input.each_with_index {|item, index|
     if (index%2 == 0) hash[item] = input[index+1]
   }
   hash   #=> {"cat"=>1, "wombat"=>3, "dog"=>2}

添加到答案,但使用匿名数组和注释:

Hash[*("a,b,c,d".split(',').zip([1,2,3,4]).flatten)]
把答案拆开,从内部开始:

  • “a,b,c,d”
    实际上是一个字符串
  • 将逗号上的
    拆分为一个数组
  • zip
    与以下数组一起使用
  • [1,2,3,4]
    是一个实际数组
中间结果是:

[[a,1],[b,2],[c,3],[d,4]]
展平然后将其转换为:

["a",1,"b",2,"c",3,"d",4]
然后:

*[“a”,1,“b”,2,“c”,3,“d”,4]
将其展开到
“a”,1,“b”,2,“c”,3,“d”,4

我们可以将其用作
Hash[]
方法的参数:

Hash[*("a,b,c,d".split(',').zip([1,2,3,4]).flatten)]
这将产生:

{"a"=>1, "b"=>2, "c"=>3, "d"=>4}

注意:有关简明有效的解决方案,请参见下文

这个答案最初是作为使用扁平化方法的替代方案提供的,扁平化是在撰写本文时投票率最高的方法。我应该澄清一下,我并不打算将此示例作为最佳实践或有效方法来展示。原来的答案如下


警告使用展平的解决方案将不会保留数组键或值

基于@John Topley的流行答案,让我们试试:

a3 = [ ['apple', 1], ['banana', 2], [['orange','seedless'], 3] ]
h3 = Hash[*a3.flatten]
这会引发一个错误:

ArgumentError: odd number of arguments for Hash
        from (irb):10:in `[]'
        from (irb):10
构造函数希望数组的长度为偶数(例如,['k1'、'v1、'k2'、'v2'])。更糟糕的是,一个不同的数组如果展平到一个偶数长度,只会悄悄地给我们一个包含错误值的散列

如果要使用数组键或值,可以使用map

h3 = Hash[a3.map {|key, value| [key, value]}]
puts "h3: #{h3.inspect}"
这将保留数组键:

h3: {["orange", "seedless"]=>3, "apple"=>1, "banana"=>2}

还可以使用以下方法将2D数组简单地转换为哈希:

1.9.3p362 :005 > a= [[1,2],[3,4]]

 => [[1, 2], [3, 4]]

1.9.3p362 :006 > h = Hash[a]

 => {1=>2, 3=>4} 

更新

。我附带了
Array#to_h
(And),它解决了将
数组
转换为
散列
的问题

Ruby文档示例:

[[:foo, :bar], [1, 2]].to_h    # => {:foo => :bar, 1 => 2}
最好的方法是使用:

请注意,
to_h
也接受一个块:

[:apple, :banana].to_h { |fruit| [fruit, "I like #{fruit}s"] } 
  # => {apple: "I like apples", banana: "I like bananas"}
注意
to_h
接受Ruby 2.6.0+中的块;对于早期的红宝石,您可以使用my
Backport
gem和

Ruby 2.1.0中引入了无块的
to_h

在Ruby 2.1之前,可以使用不太清晰的
Hash[]

array = [ [:apple,1],[:banana,2] ]
Hash[ array ]  #= > {:apple => 1, :banana => 2}

最后,要小心使用展平的任何解决方案,这可能会对数组本身的值产生问题。

如果您有这样的数组-

data = [["foo",1,2,3,4],["bar",1,2],["foobar",1,"*",3,5,:foo]]
data_hash = Hash[data.map { |key| [key.shift, key] }]

#=>{"foo"=>[1, 2, 3, 4], "bar"=>[1, 2], "foobar"=>[1, "*", 3, 5, :foo]}
您希望每个数组的第一个元素成为散列的键,其余元素成为值数组,然后您可以这样做-

data = [["foo",1,2,3,4],["bar",1,2],["foobar",1,"*",3,5,:foo]]
data_hash = Hash[data.map { |key| [key.shift, key] }]

#=>{"foo"=>[1, 2, 3, 4], "bar"=>[1, 2], "foobar"=>[1, "*", 3, 5, :foo]}
总结&TL;博士: 这个答案希望是对其他答案信息的全面总结

非常简短的版本,考虑到问题中的数据以及一些额外的内容:

flat_array   = [  apple, 1,   banana, 2  ] # count=4
nested_array = [ [apple, 1], [banana, 2] ] # count=2 of count=2 k,v arrays
incomplete_f = [  apple, 1,   banana     ] # count=3 - missing last value
incomplete_n = [ [apple, 1], [banana   ] ] # count=2 of either k or k,v arrays


# there's one option for flat_array:
h1  = Hash[*flat_array]                     # => {apple=>1, banana=>2}

# two options for nested_array:
h2a = nested_array.to_h # since ruby 2.1.0    => {apple=>1, banana=>2}
h2b = Hash[nested_array]                    # => {apple=>1, banana=>2}

# ok if *only* the last value is missing:
h3  = Hash[incomplete_f.each_slice(2).to_a] # => {apple=>1, banana=>nil}
# always ok for k without v in nested array:
h4  = Hash[incomplete_n] # or .to_h           => {apple=>1, banana=>nil}

# as one might expect:
h1 == h2a # => true
h1 == h2b # => true
h1 == h3  # => false
h3 == h4  # => true
讨论和细节如下


设置:变量 为了显示我们将要预先使用的数据,我将创建一些变量来表示数据的各种可能性。它们可分为以下几类:

根据问题的直接内容,如
a1
a2
: (注意:我假定
apple
banana
是用来表示变量的。正如其他人所做的那样,我将从这里开始使用字符串,以便输入和结果能够匹配。)

a1=['apple',1',banana',2]#平面输入
a2=[[apple',1],[banana',2]]#键/值配对输入
多值键和/或值,如
a3
: 在其他一些答案中,提出了另一种可能性(我在这里进行了扩展)——键和/或值可能是它们自己的数组:

a3=[['apple',1],
[‘香蕉’,2],
[['orange','seedless',3],,
[pear',[4,5]],
]
不平衡阵列,如
a4
: 为了更好地衡量,我想我应该在我们可能有不完整输入的情况下添加一个:

a4=[['apple',1],
[‘香蕉’,2],
[['orange','seedless',3],,
[‘榴莲’],#一个尖尖的水果刺痛了我们:没有价值!
]

现在,工作: 从最初的平面阵列开始,
a1
: 有些人建议使用(Ruby 2.1.0中出现了这一点,可以在早期版本中使用)。对于初始平面阵列,这不起作用:

a1.to_h#=>类型错误:0处的元素类型字符串错误(应为数组)
与does结合使用:

Hash[*a1]#=>{“苹果”=>1,“香蕉”=>2}
这就是用
a1
表示的简单情况的解决方案

对于键/值对数组的数组,
a2
: 对于
[key,value]
类型的数组,有两种方法

首先,
Hash::[]
仍然有效(与
*a1
一样):

Hash[a2]#=>{“苹果”=>1,“香蕉”=