PythonでもRubyみたいに配列をメソッドチェーンでつなげたい

最近は Project Euler という問題集にハマってて、とりあえず最近始めたばっかりの Pythonやってみているのだけど、Python の配列操作はどうもいちいち面倒くさい。

a = [1,4,3,2]
a.sort()    # ← これが self を返さないのとか
reversed(sorted(a))    # ← 一々戻って関数を書いたりしないといけないところとか
map(lambda x:str(x), a)    # ← 配列を起点にする動作なのに配列を最後に書くのとか
'-'.join(a)    # ← 閉口

Ruby みたいに

a = [1,4,3,2]
a.sort().reverse().map{|x| x.to_s}.join('-')

って書けたらいいのに!


というわけで BetterList.py を書いた。

sort() が破壊的で sorted() が非破壊的ということで、動詞の原型は破壊的、過去分詞型は非破壊的とした。

そのせいで a.filter(ほにゃらら) が破壊的だったりするけど、気にしない。


テスト。

#!/usr/bin/python
text = '''
from BetterList import List
a = List([2,3,1,4,2,5])
print a
b = a.uniqed().sorted()
print b
print b.map(lambda x:x+4).remove_if(lambda x:x%3==0)
print a
print a.sort()
print a
print a.filtered(lambda x:x%2==0)
print a
print a.remove_all(2)
c = List([[1,2,3],[4,[5],[6]],[[None,[7]]]])
print c
d = c.flattened()
print d
print d.compacted()
print d
print c
print c.flatten().reversed().concat([2,3,4])
print c
print c.slice(1,5)
print c.mapped(lambda x:str(x)).join('')
print c
print c.sliced(length=3)
e = d.dup()
print e
print e.sort().filter(lambda x:1<x<4).reverse().concat(b)
print e.length
print e.reduce(lambda x,y:x+y)
print d
print d.push(2).unshift(9)
print d.compacted().reduce(lambda x,y:x+str(y),'')
'''

commands = [x for x in text.split('\n') if x!='']
for command in commands:
    print('>>> %s' % command)
    exec(command)

結果

>>> from BetterList import List
>>> a = List([2,3,1,4,2,5])
>>> print a
[2, 3, 1, 4, 2, 5]
>>> b = a.uniqed().sorted()
>>> print b
[1, 2, 3, 4, 5]
>>> print b.map(lambda x:x+4).remove_if(lambda x:x%3==0)
[5, 7, 8]
>>> print a
[2, 3, 1, 4, 2, 5]
>>> print a.sort()
[1, 2, 2, 3, 4, 5]
>>> print a
[1, 2, 2, 3, 4, 5]
>>> print a.filtered(lambda x:x%2==0)
[2, 2, 4]
>>> print a
[1, 2, 2, 3, 4, 5]
>>> print a.remove_all(2)
[1, 3, 4, 5]
>>> c = List([[1,2,3],[4,[5],[6]],[[None,[7]]]])
>>> print c
[[1, 2, 3], [4, [5], [6]], [[None, [7]]]]
>>> d = c.flattened()
>>> print d
[1, 2, 3, 4, 5, 6, None, 7]
>>> print d.compacted()
[1, 2, 3, 4, 5, 6, 7]
>>> print d
[1, 2, 3, 4, 5, 6, None, 7]
>>> print c
[[1, 2, 3], [4, [5], [6]], [[None, [7]]]]
>>> print c.flatten().reversed().concat([2,3,4])
[7, None, 6, 5, 4, 3, 2, 1, 2, 3, 4]
>>> print c
[1, 2, 3, 4, 5, 6, None, 7]
>>> print c.slice(1,5)
[2, 3, 4, 5]
>>> print c.mapped(lambda x:str(x)).join('')
2345
>>> print c
[2, 3, 4, 5]
>>> print c.sliced(length=3)
[2, 3, 4]
>>> e = d.dup()
>>> print e
[1, 2, 3, 4, 5, 6, None, 7]
>>> print e.sort().filter(lambda x:1<x<4).reverse().concat(b)
[3, 2, 5, 7, 8]
>>> print e.length
5
>>> print e.reduce(lambda x,y:x+y)
25
>>> print d
[1, 2, 3, 4, 5, 6, None, 7]
>>> print d.push(2).unshift(9)
[9, 1, 2, 3, 4, 5, 6, None, 7, 2]
>>> print d.compacted().reduce(lambda x,y:x+str(y),'')
912345672