はじめに
私は基本Pythonしか書かないのですが、C#でデスクトップアプリ開発に手を出してみたりして、
パイプっぽいリストの加工便利だなーと感じ、Pythonで似たような?ことをできるようなクラスを試しに書いたメモ。
n番煎じ。
こんなの
arr = (l (range(10))
| (lambda x: 2 * x)
| (lambda x, i: x + i)
| (lambda x, i, arr: x * arr[-i-1]))
print(arr) # -> [0, 72, 126, 162, 180, 180, 162, 126, 72, 0]
使用している書体によってはl
から縦棒が連なってる感じで見た目がよい。
import requests
from bs4 import BeautifulSoup
soup = BeautifulSoup(requests.get("https://qiita.com/tags/python").content)
dict(
l (soup.find_all("li"))
| (lambda x: x.a['href'])
| (lambda x: x.split("/"))
| (lambda x, i, arr: (f"{i+1}/{len(arr)}", [i for i in l(x) if i]))
)
#-> {'1/3': ['https:', 'www.python.jp'], '2/3': ['https:', 'docs.python.org', 'ja', '3'], '3/3': ['https:', 'ja.wikipedia.org', 'wiki', 'Python']}
こういう使い方とか。
実装
ただのリストのサブクラス、引数に応じてインデックスやリスト全体を得られる点はJSのArray.prototype.map譲り。
class l(list):
def __or__(self, f):
# check is func
assert hasattr(f, "__call__")
# check num args
from inspect import signature
n = len(signature(f).parameters)
assert 0 < n <= 3
if n == 1:
return l(f(x) for x in self)
elif n == 2:
return l(f(x, i) for i, x in enumerate(self))
elif n == 3:
return l(f(x, i, self) for i, x in enumerate(self))