0
0

More than 1 year has passed since last update.

【Python】Array.prototype.mapのようなLINQのようなパイプのようなやつ

Last updated at Posted at 2023-01-18

はじめに

私は基本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))
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0