Posted at

RubyとPythonのHash(Dictionary)操作対応まとめ

More than 1 year has passed since last update.


概要

RubyのArray、PythonのHash (Dictionary) の典型的な操作のまとめ。

Python(Ruby)を学習し始めたばかりのRubyist(Pythonista)用の記事です。


前提条件


  • Python 3.5.2

  • Ruby 2.3.1


参考情報


メソッド


初期化


  • ruby

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

h2 = {a: 1, b: 2, c: 3} # symbol をkeyにする場合


  • python

d = {'a': 1, 'b': 2, 'c': 3}


要素の取り出し


  • ruby

h['c']    #=> 3

h['d'] #=> nil

d['c']    #=> 3

d['d'] #=> 例外KeyErrorが発生


size


  • ruby

h.size   #=> 3


  • python

len( d )   #=> 3


each

要素に対してループを回す


  • ruby

h.each do |key,val|

puts key,val
end


  • python

for k,v in d.items():

print(k,v)


keys, values

key,valueのリストを取得する


  • ruby

h.keys    #=> ["a", "b", "c"]

h.values #=> [1, 2, 3]

keys = d.keys()       #=> dict_keys(['b', 'a', 'c'])

values = d.values() #=> dict_values([2, 1, 3])

d['d'] = 4
keys #=> dict_keys(['b', 'd', 'a', 'c'])
values #=> dict_values([2, 4, 1, 3])

list(keys) #=> ['b', 'd', 'a', 'c']


配列から生成


  • ruby



    • Array#to_h を使うのが楽



a = [1,2,3,4]

a.map {|x| [x,x+3] }.to_h #=> {1=>4, 2=>5, 3=>6, 4=>7}


  • python


    • リスト内包表記



a = [1,2,3,4]

{ i:i+3 for i in a } #=> {1: 4, 2: 5, 3: 6, 4: 7}


key,valueのmap


  • ruby


    • keyやvalueを変換したい場合、mapを使う。map自体はArrayのArrayを返すので、それをHash[]でHashに変換する



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

h.map {|k,v| [k.upcase, -v] } #=> [["A", -1], ["B", -2], ["C", -3]]
h.map {|k,v| [k.upcase, -v] }.to_h #=> {"A"=>-1, "B"=>-2, "C"=>-3}


  • python

d = {'a': 1, 'b': 2, 'c': 3}

{ k.upper():-v for k,v in d.items() } #=> {'A': -1, 'B': -2, 'C': -3}


has_key?


  • ruby

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

h.has_key?("a") #=> true
h.has_key?("d") #=> false


  • python


    • python2までは d.has_key('a') というメソッドも使えたらしい。



d = {'a': 1, 'b': 2, 'c': 3}

'a' in d #=> True
'd' in d #=> False


merge

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

h2 = {"d" => 4, "e" => 5, "f" => 6}
h1.merge(h2)
# => {"a"=>1, "b"=>2, "c"=>3, "d"=>4, "e"=>5, "f"=>6}


  • python



    • updateというメソッドがあるが、破壊的な操作...



d1 = {"a": 1, "b": 2, "c": 3}

d2 = {"d": 4, "e": 5, "f": 6}
d1.update(d2)
d1
#=> {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6}


delete


  • ruby

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

h.delete('a') #=> 1
h #=> {"b"=>2, "c"=>3}


  • python

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

d.pop('a') #=> 1
d #=> {'b': 2, 'c': 3}


デフォルト値の設定

ヒストグラムをとったりする場合に連想配列を使うケース


  • ruby

chars = ["a", "b", "b", "c", "c", "c"]

h = Hash.new(0)
chars.each {|c| h[c] += 1 } # 文字数のカウント
h #=> {"a"=>1, "b"=>2, "c"=>3}

chars = ["a", "b", "b", "c", "c", "c"]

d = {}
for c in chars:
d[c] = d.get(c,0) + 1 # 値があれば取得し、なければ0を返す
d #=> {'a': 1, 'b': 2, 'c': 3}

from collections import defaultdict

chars = ["a", "b", "b", "c", "c", "c"]
d = defaultdict( lambda: 0 )
for c in chars:
d[c] += 1

d
# => defaultdict(<function __main__.<lambda>>, {'a': 1, 'b': 2, 'c': 3})


配列のindexを作る場合

words = ["a1", "b1", "b2", "c1", "c2", "c3"]

h = Hash.new {|hash,key| hash[key] = [] }
words.each {|w| h[ w[0] ] << w }
h
# => {"a"=>["a1"], "b"=>["b1", "b2"], "c"=>["c1", "c2", "c3"]}


  • python

words = ["a1", "b1", "b2", "c1", "c2", "c3"]

d = defaultdict( list )
for w in words:
key = w[0]
d[key].append(w)

d
#=> defaultdict(list, {'a': ['a1'], 'b': ['b1', 'b2'], 'c': ['c1', 'c2', 'c3']})