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>)