我爱编程Python

Python实现简单版linq

2018-04-13  本文已影响0人  冰麟轻武

一、

虽说Python在数据处理方面天生挺强的
但是对于一个C#开发人员来说没有linq还真是挺麻烦的

二、

反正造轮子也习惯了
那就造一个玩玩吧

三、

完整的复制一遍C#中linq的功能还是需要很多时间的
所以暂时只实现了一部分常用的功能
以后想要更多在慢慢加吧

四、

还是做了一些本地化的事情的
比如方法名都小写了...
然后也有一些限制,比如一个linq()对象只能被操作一次
因为Python中的iterable没有reset操作!!!

class linq(object):
    def __init__(self, iterable):
        if not isinstance(iterable, Iterable):
            raise TypeError('参数类型错误')
        self.__end = False
        self.__iterable = iterable

    def __get_iterable(self):
        if self.__end:
            raise StopIteration('迭代器不可重复使用')

        self.__end = True
        return self.__iterable

    def all(self, predicate):
        return all(map(predicate, self.__get_iterable()))

    def any(self, predicate=None):
        return any(map(predicate, self.__get_iterable()))

    def where(self, predicate):
        return linq(filter(predicate, self.__get_iterable()))

    def max(self):
        return max(self.__get_iterable())

    def min(self):
        return min(self.__get_iterable())

    def average(self):
        count = 0
        total = 0.0
        for number in self.__get_iterable():
            total += number
            count += 1
        return total / count

    def union(self, iterable):
        return linq(self.__union(iterable))

    def __union(self, iterable):
        for x in self.__get_iterable():
            yield x
        for x in iterable:
            yield x

    def count(self):
        count = 0
        for number in self.__get_iterable():
            count += 1
        return count

    def first(self, defaultValue=None):
        return next(self.__get_iterable(), defaultValue)

    def last(self, defaultValue=None):
        it = self.__get_iterable()
        x = None
        b = False
        while True:
            try:
                x = next(it)
                b = True
            except StopIteration:
                if b:
                    return x
                return defaultValue

    def sum(self):
        return sum(self.__get_iterable())

    def tolist(self):
        return list(self.__get_iterable())

    def select(self, selector):
        return linq(map(selector, self.__get_iterable()))

五、

测试代码

test_result = {
    "select-list": {
        "expected": linq([1, 2, 3, 4, 5, 6]).where(lambda x: x % 2 == 0).select(lambda x: x * 2).tolist(),
        "actual": [4, 8, 12]
    },
    "sum": {
        "expected": linq([1, 2, 3, 4, 5, 6]).where(lambda x: x % 2 == 0).sum(),
        "actual": 12
    },
    "max": {
        "expected": linq([1, 2, 3, 4, 5, 6]).max(),
        "actual": 6
    },
    "min": {
        "expected": linq([1, 2, 3, 4, 5, 6]).min(),
        "actual": 1
    },
    "all": {
        "expected": [linq([1, 2, 3, 4, 5, 6]).all(lambda x: x < 3),
                        linq([1, 2, 3, 4, 5, 6]).all(lambda x: x > 0), ],
        "actual": [False, True]
    },
    "any": {
        "expected": [linq([1, 2, 3, 4, 5, 6]).any(lambda x: x > 3),
                        linq([1, 2, 3, 4, 5, 6]).any(lambda x: x < 0), ],
        "actual": [True, False]
    },
    "average": {
        "expected": linq([1, 2, 3, 4, 5, 6]).average(),
        "actual": 3.5
    },
    "union": {
        "expected": linq([1, 2, 3, 4, 5, 6]).union([8, 9, 10]).tolist(),
        "actual": [1, 2, 3, 4, 5, 6, 8, 9, 10]
    },
    "count": {
        "expected": linq([1, 2, 3, 4, 5, 6]).where(lambda x: x > 1).count(),
        "actual": 5
    },
    "first": {
        "expected": linq([1, 2, 3, 4, 5, 6]).where(lambda x: x > 1).first(),
        "actual": 2
    },
    "last": {
        "expected": linq([1, 2, 3, 4, 5, 6]).where(lambda x: x < 4).last(),
        "actual": 3
    },
}

for name, result in test_result.items():
    expected = result["expected"]
    actual = result["actual"]
    if expected == actual:
        print('%s 测试成功!' % name)
    else:
        print('%s 测试失败!\n    应为: %s\n    实为: %s' % (name, actual, expected))

六、

上一篇下一篇

猜你喜欢

热点阅读