【Python】pythonでLinq風 | ツール・シミュレータ

ツール・シミュレータ

ツール・シミュレータ等のプログラミングをネタとしてブログ。

昔F#で関数型をやって以来、C#のLinqが便利すぎ!

pythonでも偽Linq風を作ってみた。

 

 

excollections.elist.py 

 

# -*- coding:utf-8 -*-

from typing import TypeVar,List,Callable,Tuple
from functools import reduce

T = TypeVar("T")
U = TypeVar("U")

class Enumerable:
    

    def __init__(self,l:List[T]):
        self.l:List[T] = l


    def tolist(self) -> List[T]:
        return self.l
    

    def all(self,f:Callable[[T],bool]) -> bool:
        for a in self.l:
            if f(a) == False:
                return False
        return True
    

    def contains(self,t:T) -> bool:
        return t in self.l
    

    def any(self,f:Callable[[T],bool]) -> bool:
        for a in self.l:
            if f(a) == True:
                return True
        return False
    

    def where(self,f:Callable[[T],bool]) -> 'Enumerable':
        r:List[T] = []
        for a in self.l:
            if f(a) == True:
                r.append(a)
        return Enumerable(r)
    

    def skip(self,c:int) -> 'Enumerable':
        return Enumerable(self.l[c:])
    

    def skip_while(self,f:Callable[[T],bool]) -> 'Enumerable':
        idx = 0
        for a in self.l:
            if f(a) == True:
                idx += 1
            else:
                break
        return Enumerable(self.l[idx:])
    

    def take(self,c:int) -> 'Enumerable':
        return Enumerable(self.l[0:c])
    

    def take_while(self,f:Callable[[T],bool]) -> 'Enumerable':
        idx = 0
        for a in self.l:
            if f(a) == True:
                idx += 1
            else:
                break
        return Enumerable(self.l[0:idx])
    

    def select(self,f:Callable[[T],U]) -> 'Enumerable':
        r:List[U] = []
        for a in self.l:
            r.append(f(a))
        return Enumerable(r)
    

    #def order_by


    def concat(self,t:List[T]) -> 'Enumerable':
        r:List[T] = []
        r.extend(self.l)
        r.extend(t)
        return Enumerable(t)
    

    def count(self) -> int:
        return len(self.l)
    

    def aggregate(self,init:U,f:Callable[[U,T],U]) -> U:
        acc = init
        for a in self.l:
            acc = f(acc,a)
        return acc
    

    def divide(self,f:Callable[[T],bool]) -> Tuple['Enumerable','Enumerable']:
        tr:List[T] = []
        fl:List[T] = []
        for a in self.l:
            if f(a):
                tr.append(a)
            else:
                fl.append(a)
        return (Enumerable(tr),Enumerable(fl))
    
    
    def flatten(self) -> 'Enumerable':
        return Enumerable(reduce(lambda a,b : a + b,self.l))