pipe.LINQ的なライブラリ
なにこれ?
こんなことができる(pypiのサンプルより)
フィボナッチ数列の4000000以下の偶数の総和が欲しい
euler2 = fib() | where(lambda x: x % 2 == 0) | take_while(lambda x: x < 4000000) | add
全部の関数の例を作ってみる。
出力を伴う
lineout,stdout
lineoutは末尾に改行を付ける。stdoutはそのまま出力
import pipe "foo" | pipe.lineout "foo" | pipe.stdout 12 | pipe.stdout # foo # foo12
tee
teeは(特にイテレータを)標準出力に改行付きで吐き出してくれるイテレータを返す。rubyのtappのイテレータ版のような(tappは受け取ったオブジェクトを出力して、そのまま返す)。
# これはruby class Object def tapp self.tap{|x| p x} end end p 10.tapp * 10 # 10 # 100
こっちはpython
import pipe xs = [i*i for i in range(5) | pipe.tee] xs | pipe.lineout # 0 # 1 # 2 # 3 # 4 # [0, 1, 4, 9, 16]
netcat
渡された文字列を開いたソケットに送る。
import pipe message = "GET / HTTP/1.0\r\nHost: www.google.co.jp\r\n\r\n" result = [line for line in message | pipe.netcat('www.google.co.jp', 80) | pipe.tee] ## httpリクエストが流れる。, resultに結果がたまる
netwriteもある。
traverse, as_list, as_tupple, as_dict
travarseは、イテレータを再帰的にたどって行ってyield(あまり効率はよくない..と思う。)
import pipe ## listを再帰的に for e in [1, [2, 3,[4, [5]]], [6, [7, 8]]] | pipe.traverse: print "%s, " % e, print "\n------" ## dictはkeyだけ for e in {"key0": {"key01": 1}, "key1": [1, 2, 3]} | pipe.traverse: print "%s, " % e, print "\n------" ## リスト内包表記と使うとflatten def flatten(xs): return [e for e in xs | pipe.traverse] print flatten([1, [2, 3,[4, [5]]], [6, [7, 8]]]) # 1, 2, 3, 4, 5, 6, 7, 8, # ------ # key1, key0, # ------ # [1, 2, 3, 4, 5, 6, 7, 8]
構造の変換
concat
文字列にする。string.joinを呼ぶ。
import pipe [1, 2, 3, 4] | pipe.concat(", ") | pipe.lineout # 1, 2, 3, 4
as_dict, as_list, as_tupple
再帰的ではない。
import pipe print [[1, 2], [3, 4]] | pipe.as_dict print [1, 2, 3] | pipe.as_tuple print [1, [2, 3], 4] | pipe.as_tuple print {"k0": 2, "k1" : [4, 5]} | pipe.as_list print {"k0": 2, "k1" : [4, 5]} | pipe.as_tuple # {1: 2, 3: 4} # (1, 2, 3) # (1, [2, 3], 4) # ['k1', 'k0'] # ('k1', 'k0')
構造中の要素を変換(うまく言えない)
sort, reverse
import pipe [1, 3, 5, 3, 1] | pipe.reverse | pipe.concat | pipe.lineout print [1, 3, 5, 3, 1] | pipe.sort # 1, 3, 5, 3, 1 # [1, 1, 3, 3, 5]
permutations, chain
順列生成とイテレータ同士をつなげる(ひとつが終わったら次のというように)
import pipe [1, 2, 3] | pipe.permutations | pipe.concat | pipe.stdout # (1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1) [[1, 2, 3], [10, 20]] | pipe.chain | pipe.concat | pipe.lineout # 1, 2, 3, 10, 20
where, select
import pipe out = pipe.Pipe(lambda x : x | pipe.concat | pipe.lineout) [1, 2, 3] | pipe.where (lambda x : x % 2 == 1) | out [1, 2, 3] | pipe.select (lambda x : x * x) | out # 1, 3 # 1, 4, 9
選択
first, take, tail, skip
import pipe out = pipe.Pipe(lambda x : x | pipe.concat | pipe.lineout) [1, 2, 3] | pipe.first | pipe.lineout [1, 2, 3] | pipe.take(2) | out [1, 2, 3] | pipe.tail(2) | out [1, 2, 3] | pipe.skip(2) | out # 1 # 1, 2 # 2, 3 # 3
take_while, skip_while
import pipe out = pipe.Pipe(lambda x : x | pipe.concat | pipe.lineout) # *** first, take, tail, skip [1,1,1, 2, 3] | pipe.take_while (lambda x : x == 1) | out [1,1,1, 2, 3] | pipe.skip_while (lambda x : x == 1) | out # 1, 1, 1 # 2, 3
合算?(aggregate)
all, any
import pipe print [1, 1, 1] | pipe.all (lambda x : x == 1) print [1, 2, 4] | pipe.all (lambda x : x == 1) print [1, 2, 4] | pipe.any (lambda x : x == 1) print [8, 2, 4] | pipe.any (lambda x : x == 1) # True # False # True # False
average, add, count, max, min
import pipe print range(1, 11) print range(1, 11) | pipe.add print range(1, 11) | pipe.count print range(1, 11) | pipe.max print range(1, 11) | pipe.min print range(1, 11) | pipe.select (lambda x : x * x) | pipe.add # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # 55 # 10 # 10 # 1 # 385
すこし複雑。
aggregate, groupby
import pipe print range(1, 11) | pipe.aggregate(lambda n, x : n + x) print range(1, 11) | pipe.aggregate(lambda n, x : n * x) print range(1, 11) | pipe.aggregate(lambda n, x : n + x*x) out = pipe.Pipe(lambda x : x | pipe.concat | pipe.lineout) [1, 1, 1, 2, 2, 3, 1, 1] | pipe.groupby(int) | out # 55 # 3628800 # 385 # (1, <itertools._grouper object at 0x7f84dc10d950>), (2, <itertools._grouper object at 0x7f84dc10d950>), (3, <itertools._grouper object at 0x7f84dc10d950>)