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