Python实现简易Linq

一、引入

  个人觉得C#的Linq是非常好用的语法糖,对于List的处理非常方便且高效。但是在Python中没有现成的类似于Linq的类库,于是想着自己写一个。

二、代码部分

class LinQUtil(object):
    """
    模拟C#的linq功能
    """

    def __init__(self, collection):
        """
        初始化
        :param collection:需要处理的list
        """
        self.collection = collection

    def where(self, func):
        """
        根据where添加查询
        :param func: 处理的函数
        :return:
        """
        try:
            return list(filter(func, self.collection))
        except Exception as e:
            print(e)
            return list()

    def first_or_default(self, func):
        try:
            res = list(filter(func, self.collection))
            if res:
                return res[0]
            else:
                return dict()
        except Exception as e:
            print(e)
            return dict()


def main():
    # 从数据库查询出形如:[{},{}...]的数据
    data_list = get_user_list_dal()
    data_list_where = LinQUtil(data_list).first_or_default(func=lambda x: x.get('city_id') == 73)
    print(data_list_where)
    print(len(data_list_where))


if __name__ == '__main__':
    main()

三、基于bisect库实现单条件的精确查找(效率提升)

  Python有一个库bisect,这个库本身是用来实现排序的,但是这个库中有一个bisect.bisect(data_list,data),这个就厉害了,可以查找该数值将会插入的位置并返回,而不会插入。衍生出来bisect_left 和 bisect_right 函数就可以用来实现上述LinQUtils类中的方法了,

  具体代码如下:

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 # @Time:2020/4/21 11:02
 4 # @Software:PyCharm
 5 __author__ = "JentZhang"
 6 import bisect
 7 from utils.base_func import timer
 8 
 9 
10 def get_list_by_key(data_list, val, key_val_list):
11     """
12     通过二分查找获取指定key和val的数据,LinQUtils的升级版
13     :param data_list:数据集合嵌套数组,必须是排序之后的
14     :param val:
15     :param key_val_list:排序之后所有的指定key的val集合
16     :return:
17     """
18     import bisect
19     result = list()
20     if key_val_list:
21         # 获取集合中指定数据最左边的位置
22         data_start = bisect.bisect_left(key_val_list, val)
23         # 获取集合中指定数据最右边的位置
24         data_end = bisect.bisect_right(key_val_list, val)
25         if data_start < data_end:
26             # 截取嵌套数组符合条件的数据
27             data_where = data_list[data_start:data_end]
28             result = data_where
29 
30     return result
31 
32 
33 @timer
34 def main():
35     data_list = [i for i in range(10000000)]
36     res = get_list_by_key(data_list, val=9695465, key_val_list=data_list)
37     print(res)
38 
39 
40 if __name__ == '__main__':
41     main()

  执行结果:

  

   在一千万的数据中,这个方法只需要不到一秒的时间就能实现精确查找!

  针对LinQ中单个查询条件的筛选,完全可以借助bisect来实现,比filter()的方法快的多得多!!!!

四、总结

  这里先简单实现一下where和first_or_default的功能,后面再慢慢补充其他的。。。。。。

  其实,实现linq基础类就是基于Python的高级函数 filter()

  使用这里的Linq使我的匹配数据的过程相较于原来使用list循环来做节省了一半左右的时间。

        灵活运用python的高级函数如:filter(),map(),reduce()等真的可以大大增加数据处理的效率。

原文地址:https://www.cnblogs.com/JentZhang/p/12664659.html