134

Rubyでは、次のいずれかの形式の配列を指定します...

[apple, 1, banana, 2]
[[apple, 1], [banana, 2]]

...これを次の形式のハッシュに変換するための最良の方法は何ですか...

{apple => 1, banana => 2}
4

12 に答える 12

149

単に使用するHash[*array_variable.flatten]

例えば:

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#flatten(1)すると再帰が制限されるため、Arrayキーと値は期待どおりに機能します。

于 2008-09-02T14:14:08.340 に答える
99

: 簡潔で効率的な解決策については、以下の Marc-André Lafortune の回答を参照してください。

この回答はもともと、執筆時点で最も支持されていた flatten を使用したアプローチの代替として提供されました。この例をベスト プラクティスや効率的なアプローチとして提示するつもりはないことを明確にする必要がありました。元の答えは次のとおりです。


警告!flattenを使用したソリューションでは、配列のキーまたは値が保持されません!

@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'])。さらに悪いことに、偶数の長さにフラット化された別の Array は、暗黙のうちに誤った値のハッシュを提供するだけです。

配列のキーまたは値を使用する場合は、mapを使用できます。

h3 = Hash[a3.map {|key, value| [key, value]}]
puts "h3: #{h3.inspect}"

これにより、配列キーが保持されます。

h3: {["orange", "seedless"]=>3, "apple"=>1, "banana"=>2}
于 2012-03-05T18:17:39.410 に答える
22

アップデート

Ruby 2.1.0 が本日リリースされました。また、 を に変換する際の問題を解決するArray#to_h(リリース ノートruby​​-doc )が付属しArrayていHashます。

Ruby ドキュメントの例:

[[:foo, :bar], [1, 2]].to_h    # => {:foo => :bar, 1 => 2}
于 2013-12-25T22:22:36.917 に答える
9

編集:私が書いている間に投稿された応答を見ました、ハッシュ[a.flatten]は行く方法のようです。私が応答を考えていたとき、ドキュメントのそのビットを見逃したに違いありません。私が書いた解決策は、必要に応じて代替手段として使用できると考えました。

2番目の形式はより単純です:

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 }
于 2008-09-02T14:16:01.363 に答える
5

以下を使用して、単純に 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} 
于 2013-01-11T13:54:40.443 に答える
3

回答に追加しますが、匿名配列を使用して注釈を付けます:

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

内部から始めて、その答えを分解します。

  • "a,b,c,d"実際には文字列です。
  • splitコンマで配列に。
  • zipそれは次の配列と一緒です。
  • [1,2,3,4]実際の配列です。

中間結果は次のとおりです。

[[a,1],[b,2],[c,3],[d,4]]

flatten 次に、それを次のように変換します。

["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}
于 2010-06-16T19:14:25.910 に答える
0

それが最善の方法かどうかはわかりませんが、これは機能します。

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
于 2008-09-02T14:16:35.120 に答える
0

このような配列がある場合-

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]}
于 2015-03-12T11:27:22.487 に答える
-1

数値が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}
于 2008-09-02T14:20:27.640 に答える