はじめに
移植やってます。
( from python 3.7 to ruby 2.7 )
itemgetter (Python)
def itemgetter(*items):
if len(items) == 1:
item = items[0]
def g(obj):
return obj[item]
else:
def g(obj):
return tuple(obj[item] for item in items)
return g
>>> itemgetter(1)('ABCDEFG')
'B'
>>> itemgetter(1,3,5)('ABCDEFG')
('B', 'D', 'F')
>>> itemgetter(slice(2,None))('ABCDEFG')
'CDEFG'
>>> soldier = dict(rank='captain', name='dotterbart')
>>> itemgetter('rank')(soldier)
'captain'
便利なのかも。
def (Ruby)
def itemgetter(obj, *items)
if items.size == 1
item = items[0]
def g(obj, *items)
item = items[0]
return obj[item]
end
else
def g(obj, *items)
return items.map{ |item| obj[item] }
end
end
return g(obj, *items)
end
p itemgetter('ABCDEFG', 1)
p itemgetter('ABCDEFG', 1, 3, 5)
p itemgetter('ABCDEFG', 2..)
soldier = {'rank' => 'captain', 'name' => 'dotterbart'}
p itemgetter(soldier, 'rank')
# output
"B"
["B", "D", "F"]
"CDEFG"
"captain"
引数の順番を合わせるようにブロックを使用した方がかっこいいかもしれないのですが。
lambda (Ruby)
ig1 = lambda { |x| x[1] }
ig2 = lambda { |x| [1, 2, 3].map{ x[_1] } }
ig3 = lambda { |x| (2..x.size.pred).map{ x[_1] }.join('') }
soldier = {'rank' => 'captain', 'name' => 'dotterbart'}
ig4 = lambda { |x| soldier[x] }
p ig1.call('ABCDEF')
p ig2.call('ABCDEF')
p ig3.call('ABCDEF')
p ig4.call('rank')
# output
"B"
["B", "C", "D"]
"CDEF"
"captain"
一つ目の引数と二つ目の引数が同時に呼ばれない様なので、こういうのもありかも。
class (Ruby)
class Itemgetter
def initialize(*items)
if items.size == 1
@item = items[0]
else
@items = items
end
end
def g(obj)
if @item
obj[@item]
else
@items.map{ |item| obj[item] }
end
end
end
ig1 = Itemgetter.new(1)
ig2 = Itemgetter.new(1, 2, 3)
ig3 = Itemgetter.new(2..)
ig4 = Itemgetter.new('rank')
p ig1.g('ABCDEF')
p ig2.g('ABCDEF')
p ig3.g('ABCDEF')
soldier = {'rank' => 'captain', 'name' => 'dotterbart'}
p ig4.g(soldier)
# output
"B"
["B", "C", "D"]
"CDEF"
"captain"
クラスの方がスッキリかな。
メモ
- Python の itemgetter を学習した
- 百里を行く者は九十里を半ばとす