2017-04-08 5 views
1

私は約860個の配列を持っています。ハッシュに変換したいのですが、配列構造は(Key1、value1、value2、value3、Key2、value1、value 2、値3 ...........等)のように見える(Peter、150,39,345、John、123、450、402、Mary、145、345、506。 ...........)。オリジナルのものは4つの配列なので、4つの独立した配列から同じ目的を達成することができます。配列をハッシュに分割する

私は十分にルビーを知らない可能性があるため、私はこれを行うには素敵なきちんとした方法があるはず感じるが、それは私を見逃さ

Hash {Peter=> [150, 39, 345], John=>[123,450,402], Mary => [145,345,506] etc etc 

をしたいと思います。あなたは、データが4のセットで常にあることがわかっている場合

+0

を試してみてください?あなたは本当に元の配列が何であるかは述べていませんが、配列の連結をスキップする方が簡単かもしれないようです。 –

答えて

1

:あなたが知っていれば

l = ['Peter', 150, 39, 345, 'John', 123, 450, 402, 'Mary', 145, 345, 506] 
h = {} 
l.each_slice(4).each do |chunk| 
    h[chunk[0]] = chunk[1..chunk.length] 
end 

代わりに、キーは常に文字列である:基本的に

l = ['Peter', 150, 39, 345, 'John', 123, 450, 402, 'Mary', 145, 345, 506] 
h = {} 
current_key = "" 
l.each do |item| 
    if item.is_a? String 
     current_key = item 
     h[item] = [] 
    else 
     h[current_key] << item 
    end 
end 

、あなたはどのように出て作業する必要がありますアレイを適切にスライスしてループスルーします。あなたは既に別の配列としてそれらを持っている場合

はまた、あなただけで簡単にできます。私は主張したい

array_1 = ['Peter', 150, 39, 345] 
array_2 = ['John', 123, 450, 402] 
array_3 = ['Mary', 145, 345, 506] 
h = {}  

[array_1,array_2, array_3].each do |a| 
    h[a[0]] = a[1:a.length] 
end 

# One line version: 
[array_1,array_2, array_3].map{|a| h[a[0]] = a[1..a.length]} 

は最もクリーンな方法です。

4

もう一つの方法:

l = ['Peter', 150, 39, 345, 'John', 123, 450, 402, 'Mary', 145, 345, 506] 

Hash[*l.each_slice(4).flat_map { |a, *b| [a, b] }] 
#=> {"Peter"=>[150, 39, 345], 
# "John" =>[123, 450, 402], 
# "Mary" =>[145, 345, 506]} 

すでに配列を持っている場合は、解決策は、よりシンプルになります

arrays = [array_1, array_2, array_3] 
Hash[*arrays.flat_map {|a, *b| [a, b]} ] 
#=> {"Peter"=>[150, 39, 345], "John"=>[123, 450, 402], "Mary"=>[145, 345, 506]} 
3
arr = ['Peter', 150, 39, 345, 'John', 123, 450, 'Mary', 145, 345, 506, 222] 

arr.slice_before {|a| String === a }. 
    each_with_object({}) {|(f,*rest), h| h[f] = rest} 
    #=> {"Peter"=>[150, 39, 345], "John"=>[123, 450], "Mary"=>[145, 345, 506, 222]} 

Enumerable#slice_beforeは、Ruby V2.3でデビューしました。あるいは、v2.2で新しく追加されたEnumerable#slice_whenを使用することもできます。

これまでのバージョンのRubyで動作する方法がいくつかあります。

arr.chunk { |e| String === e }. 
    each_slice(2). 
    with_object({}) { |((_,(k)),(_,v)), h| h[k] = v } 

a = [] 
enum = arr.to_enum 
loop do 
    o = enum.next 
    (String === o) ? a << [o,[]] : a.last.last << o 
end 
Hash[a] 
1

オリジナルこれらは、私が一緒に移調している4つの配列されているので、私は4つの独立した配列から開始することにより、同じ最終目標を達成することができます。

a = ["Peter", "John", "Mary"] 
b = [150, 123, 145] 
c = [39, 450, 345] 
d = [345, 402, 506] 

あなたはzipを経由して、「値」の配列を組み合わせることができます:

values = b.zip(c, d) 
#=> [[150, 39, 345], [123, 450, 402], [145, 345, 506]] 

をを介して「キー」列を追加し、私はあなたが開始するには、このような何かを持っていると仮定し

別のzip

a.zip(values) 
#=> [["Peter", [150, 39, 345]], ["John", [123, 450, 402]], ["Mary", [145, 345, 506]]] 

これは、既に正しい構造であるので、我々はちょうどto_hを呼び出すことができます。

もちろん
a.zip(values).to_h 
#=> {"Peter"=>[150, 39, 345], "John"=>[123, 450, 402], "Mary"=>[145, 345, 506]} 

あなたが同じ結果を返すa.zip(b.zip(c, d)).to_h中間変数を、必要はありません。

+1

また、2番目の 'zip'の代わりに' transpose'を使うこともできます: 'Hash [a.zip([b、c、d] .transpose)]' – Ilya

+0

...または '[a、b、c、d]。 transpose.each_with_object({}){|(k、* v)、h | h [k] = v} 'となる。 –

0

値の配列は、すべて同じ長さであなただけの適切なハッシュエントリに各項目を反復処理し、追加できませんでしたしている場合は、この

l = ['Peter', 150, 39, 345, 'John', 123, 450, 402, 'Mary', 145, 345, 506] 

l.each_slice(4).to_a.inject({}){|acc, temp| acc[temp.first]=temp.last(3); acc} 

#=>{"Peter"=>[150, 39, 345], "John"=>[123, 450, 402], "Mary"=>[145, 345, 506]}