python 数据结构中被忽视的小技巧

来源:互联网 发布:程序员一般工资多少 编辑:程序博客网 时间:2024/05/24 05:52

一、一个包含N个元素的字符串、元组、序列、以及任何可迭代对象均可以拆分成N个单独的“变量”

  1.字符串的拆分

1 #字符串2 In [10]: s="abdefg"3 In [11]: o, p, q, x, y, z = s
4 In [12]: q5 Out[12]: 'd'6 In [13]: x7 Out[13]: 'e'8 In [14]: z9 Out[14]: 'g'

  2.列表、元组、集合和可迭代对象的拆分

 1 list_l = [1,2,3,4] 2   3 In [16]: tuple_l = [5,6,7,8] 4   5 In [17]: a,b,c,d = list_l 6  7 In [18]: b 8 Out[18]: 2 9  10 In [19]: c11 Out[19]: 312  13 In [20]: d14 Out[20]: 415  16 In [21]: m,n,o,p = tuple_l17  18 In [22]: o19 Out[22]: 720  21 In [23]: p22 Out[23]: 823  24 25 d={'k1':'v1','k2':'v2'}26  27 In [2]: d28 Out[2]: {'k1': 'v1', 'k2': 'v2'}29  30 In [3]: key1,key2 = d.keys()31 32 In [4]: key133 Out[4]: 'k2'34  35 In [5]: key236 Out[5]: 'k1'

  一个综合的例子:

 1 In [11]: data = [1,2,[3,4,6],(7,8,9),{'k1':'v1','k2':2}] 2 In [12]: a,b,li,tup,dic = data 3 In [13]: a 4 Out[13]: 1 5 In [14]: b 6 Out[14]: 2 7 In [15]: tup 8 Out[15]: (7, 8, 9) 9 In [16]: dic10 Out[16]: {'k1': 'v1', 'k2': 2}11 In [17]: li12 Out[17]: [3, 4, 6]

  问题1:如果想丢弃分解后的一些无用值怎么办?可以使用用不到的变量名"_"进行分割:

1 l=['money','money','no use','nouse','money']2 In [19]: a,b,_,_,e=l3 In [20]: print(a,b)4 money money5 In [21]: print(a,b,e)6 money money money

  问题2:如果一个可迭代对象比较长,且大于要分割的数目怎么办?"*表达式"就该发挥作用了

l=range(1,100)In [24]: len(l)Out[24]: 99In [25]: first,*p,last = l #p是一个列表[2,...,98]In [26]: print (first,len(p),last)1 97 99

In [1]: l=range(1,100)
In [2]: *q,m,n = l
In [3]: print (len(q),m,n) #q是一个列表[1,...,96]
97 98 99
In [4]: x,y,*z=l
In [5]: print(x,y,len(z))
1 2 97

同样的,“*_”也可以作为看可以丢弃的无用的变量名
In [11]: l=range(1,100)
In [12]: first,*_,end = l
In [13]: print(first,end)
1 99

二、python标准库collections模块的常见应用

  1. deque类,优点:可以在两端执行添加和弹出,并且效率更高

 1 from collections import deque 2 # 创建一个总长度为5的deque对象 3 # 默认maxlen=None,无限长度 4 dq = deque(maxlen=5) 5 print(dq) 6 # out:deque([], maxlen=5) 7 # append、appendleft方法 8 dq.append(1) 9 print(dq)10 # out:deque([1], maxlen=5)11 dq.appendleft(2)12 print(dq)13 # out:deque([2, 1], maxlen=5)14 # 插入序列列表、元组都可以15 dq.extend([5,6])16 print(dq)17 # out:deque([2, 1, 5, 6], maxlen=5)18 dq.extendleft([7,8,9])19 print(dq)20 # out:deque([9, 8, 7, 2, 1], maxlen=5)21 # 从末尾pop出来一个元素:122 dq.pop()23 print(dq)24 # out:deque([9, 8, 7, 2], maxlen=5)25 # 从开头出pop出来一个元素:926 dq.popleft()27 print(dq)28 # out:deque([8, 7, 2], maxlen=5)29 # 复制一份,相互独立30 dq_copy = dq.copy()31 print(dq,dq_copy)32 # out:deque([8, 7, 2], maxlen=5) deque([8, 7, 2], maxlen=5)33 # dq.index(x)返回x在dq中的索引34 print(dq.index(7))35 # out:136 # dq.count(x)返回dq中x的数目37 print(dq.count(7))38 # out:139 # 返回容量40 print(dq.maxlen)41 # out:542 # dq.insert(index,x) 在index处插入x43 dq.insert(0,110)44 print(dq)45 # out:deque([110, 8, 7, 2], maxlen=5)46 # dq.remove(x)从dq中移除x47 try:48     dq.remove(99)49 except Exception as e:50     print(e)51 # out:deque.remove(x): x not in deque52 #dq.reverse(),转置53 dq.reverse()54 print(dq)55 # out:deque([2, 7, 8, 110], maxlen=5)56 for i in dq:57     print(i)58 '''59 260 761 862 11063 '''64 # 清空所有元素65 dq.clear()66 print(dq)67 # deque([], maxlen=5)68 #^_^ over

  2. defaultdict类,定义一个字典对象.优点:非常容易的实现一Key多Vallue的字典

    例如;d={'a':[1,2,3,4],'b':[5,7]} ,s={'a':{2,3,4},'b':{4,5}}

    实例化:d=defaultdict(list|set) 列表、集合根据需要设置,效果如上.(元素去重用set,保持元素顺序用list)

    

 1 ''' 2 default一大优点就是创建实例的同时就已经初始化了一个可能会用到的值例如下列中的d1['a']、d2['a'] 3 ''' 4 In [5]: d1=dict() 5 In [6]: from collections import defaultdict 6 In [7]: d2=defaultdict(list) 7 In [8]: print(d1['a']) 8 --------------------------------------------------------------------------- 9 KeyError                                  Traceback (most recent call last)10 <ipython-input-8-1877cceef97a> in <module>()11 ----> 1 print(d1['a'])12 KeyError: 'a'13 In [9]: print(d2['a'])14 []

 

  看一个我遇到的使用defaultdict的比较好的例子:

 1 from collections import defaultdict 2 '''完整代码不贴了,用一个列表简化一下当时我的需求: 3 计算下面列表中的每一个元素split后的第二个元素是y的个数(即:string.split()[1]=='y'),并且与string.split()[0]一 一对应.
4 ''' 5 6 l=['a y','a n','a n','a n','a y','a y','a y''a y','b n','b n','b y','b y','b n','b y'] 7 8 d=defaultdict(list) 9 for i in l:10 if i.split()[1]=='y':11 d[i.split()[0]].append(1) #这一步完全忽视i.split()[0]是什么东西,就是干,换了dict()肯定要先定义一个key了。。。比如d=dict();d['a']=[];12 for k,v in d.items():13 print('{}:{}次'.format(k,len(v)))
--------------------------------------------
b:3次    #直到这里才知道都是么鬼,几个鬼
a:3次

  3.OrderedDict类,看名字就跟顺序有关,是的,它的作用是让存入字典的k,v对保持插入时的顺序(数据量较大时需要考虑性能)

  

 1 In [10]: from collections import OrderedDict 2  3 In [11]: d=OrderedDict() 4  5 In [12]: d['a']=1 6  7 In [13]: d['b']=2 8  9 In [14]: d['c']=310 11 In [15]: d['d']=412 13 In [16]: for k in d:14    ....:     print(k,d[k])15    ....:16 ------------------------------------17 a 118 b 219 c 320 d 4

 4.Counter类.能够简单快捷的返回序列中出现次数最多的元素和个数.

 

1 >>> l = []2 >>> for i in range(1,20):3 ...     l.append(chr(random.randint(97,100)))  #这里我们并不知道都随机生成了什么字符列表,但是大致知道是[a-d]4 ... 5 >>> list_count = Counter(l)    #实例Counter对象6 >>> top_three = list_count.most_common(3)  #取出啊前三个出现次数最多的元素7 >>> print (top_three)8 [('a', 8), ('d', 4), ('b', 4)]  

 

  假如我们知道里面有一个字符(比如'a')出现了很多次,想要得到具体多少次呢?

>>> list_count['a']8>>> list_count['b']4>>> list_count['d']4>>> list_count['c']3>>> print(list_count['e'])0>>> print(l)['a', 'd', 'a', 'd', 'a', 'b', 'a', 'a', 'd', 'b', 'd', 'a', 'a', 'a', 'c', 'c', 'c', 'b', 'b']

  操作跟字典真是太像了,没错看一下Counter类的定义,以及其它用法

class Counter(dict):#没错,继承自字典。。。    '''Dict subclass for counting hashable items.  Sometimes called a bag    or multiset.  Elements are stored as dictionary keys and their counts    are stored as dictionary values.    >>> c = Counter('abcdeabcdabcaba')  # count elements from a string    >>> c.most_common(3)                # three most common elements    [('a', 5), ('b', 4), ('c', 3)]    >>> sorted(c)                       # list all unique elements    ['a', 'b', 'c', 'd', 'e']    >>> ''.join(sorted(c.elements()))   # list elements with repetitions    'aaaaabbbbcccdde'    >>> sum(c.values())                 # total of all counts    15    >>> c['a']                          # count of letter 'a'    5    >>> for elem in 'shazam':           # update counts from an iterable    ...     c[elem] += 1                # by adding 1 to each element's count    >>> c['a']                          # now there are seven 'a'    7    >>> del c['b']                      # remove all 'b'    >>> c['b']                          # now there are zero 'b'    0    >>> d = Counter('simsalabim')       # make another counter    >>> c.update(d)                     # add in the second counter    >>> c['a']                          # now there are nine 'a'    9    >>> c.clear()                       # empty the counter    >>> c    Counter()    Note:  If a count is set to zero or reduced to zero, it will remain    in the counter until the entry is deleted or the counter is cleared:    >>> c = Counter('aaabbc')    >>> c['b'] -= 2                     # reduce the count of 'b' by two    >>> c.most_common()                 # 'b' is still in, but its count is zero    [('a', 3), ('c', 1), ('b', 0)]    '''

三、通过公共键,对字典列表排序(sorted),最大值(max),最小值(min)

  方法-1:使用operator.itemgetter

from operator import itemgetterl = [    {'name': '股票1','num': '000001','price': 13.7},    {'name': '股票2','num': '000002','price': 15.7},    {'name': '股票4','num': '000004','price': 16.7},    {'name': '股票3','num': '000003','price': 10.7}]print(l)sort_by_bum = sorted(l,key=itemgetter('num'))sort_by_price = sorted(l,key=itemgetter('price'))print(sort_by_bum)print(sort_by_price)---------------------------[{'name': '股票1', 'num': '000001', 'price': 13.7}, {'name': '股票2', 'num': '000002', 'price': 15.7}, {'name': '股票4', 'num': '000004', 'price': 16.7}, {'name': '股票3', 'num': '000003', 'price': 10.7}][{'name': '股票1', 'num': '000001', 'price': 13.7}, {'name': '股票2', 'num': '000002', 'price': 15.7}, {'name': '股票3', 'num': '000003', 'price': 10.7}, {'name': '股票4', 'num': '000004', 'price': 16.7}][{'name': '股票3', 'num': '000003', 'price': 10.7}, {'name': '股票1', 'num': '000001', 'price': 13.7}, {'name': '股票2', 'num': '000002', 'price': 15.7}, {'name': '股票4', 'num': '000004', 'price': 16.7}]

---------------------------------------------------
from operator import itemgetter
l = [
{'name': '股票1','num': '000001','price': 13.7},
{'name': '股票2','num': '000002','price': 15.7},
{'name': '股票3','num': '000003','price': 16.7},
{'name': '股票3','num': '000003','price': 10.7}
]
print(l)
sort_by_num_price = sorted(l,key=itemgetter('num','price'))
print(sort_by_num_price)

---------------------------
[{'price': 13.7, 'num': '000001', 'name': '股票1'}, {'price': 15.7, 'num': '000002', 'name': '股票2'}, {'price': 16.7, 'num': '000003', 'name': '股票4'}, {'price': 10.7, 'num': '000003', 'name': '股票3'}]
[{'price': 13.7, 'num': '000001', 'name': '股票1'}, {'price': 15.7, 'num': '000002', 'name': '股票2'}, {'price': 10.7, 'num': '000003', 'name': '股票3'}, {'price': 16.7, 'num': '000003', 'name': '股票4'}]

 

  方法-2:区别仅仅在于key后面函数的实现方式.无论lambda,itemgetter都是定义了一个func

  func(x) = lambda x:x['num'] ==>return x['num']

  func = itemgetter('num')      func(r)==>return r['num']

 

#使用匿名函数lambdal = [    {'name': '股票1','num': '000001','price': 13.7},    {'name': '股票2','num': '000002','price': 15.7},    {'name': '股票4','num': '000004','price': 16.7},    {'name': '股票3','num': '000003','price': 10.7}]print(l)sort_by_bum = sorted(l,key=lambda x:x['num'])sort_by_price = sorted(l,key=lambda x:x['price'])print(sort_by_bum)print(sort_by_price)-------------------------[{'name': '股票1', 'num': '000001', 'price': 13.7}, {'name': '股票2', 'num': '000002', 'price': 15.7}, {'name': '股票4', 'num': '000004', 'price': 16.7}, {'name': '股票3', 'num': '000003', 'price': 10.7}][{'name': '股票1', 'num': '000001', 'price': 13.7}, {'name': '股票2', 'num': '000002', 'price': 15.7}, {'name': '股票3', 'num': '000003', 'price': 10.7}, {'name': '股票4', 'num': '000004', 'price': 16.7}][{'name': '股票3', 'num': '000003', 'price': 10.7}, {'name': '股票1', 'num': '000001', 'price': 13.7}, {'name': '股票2', 'num': '000002', 'price': 15.7}, {'name': '股票4', 'num': '000004', 'price': 16.7}]

---------------------------------------------------分割线--
l = [
{'name': '股票1','num': '000001','price': 13.7},
{'name': '股票2','num': '000002','price': 15.7},
{'name': '股票3','num': '000003','price': 16.7},
{'name': '股票3','num': '000003','price': 10.7}
]
print(l)
sort_by_num_price = sorted(l,key=lambda x:(x['num'],x['price']))
print(sort_by_num_price)

---------------------------
[{'price': 13.7, 'num': '000001', 'name': '股票1'}, {'price': 15.7, 'num': '000002', 'name': '股票2'}, {'price': 16.7, 'num': '000003', 'name': '股票4'}, {'price': 10.7, 'num': '000003', 'name': '股票3'}]
[{'price': 13.7, 'num': '000001', 'name': '股票1'}, {'price': 15.7, 'num': '000002', 'name': '股票2'}, {'price': 10.7, 'num': '000003', 'name': '股票3'}, {'price': 16.7, 'num': '000003', 'name': '股票4'}]

 

最大值,最小值,max,min

from operator import itemgetterl = [    {'name': '股票1','num': '000001','price': 13.7},    {'name': '股票2','num': '000002','price': 15.7},    {'name': '股票4','num': '000004','price': 16.7},    {'name': '股票3','num': '000003','price': 10.7}]max = max(l,key=itemgetter('price'))min = min(l,key=itemgetter('price'))print(max)print(min)-----------------------------{'num': '000004', 'price': 16.7, 'name': '股票4'}{'num': '000003', 'price': 10.7, 'name': '股票3'}

 四.高阶函数map/filter/sorted

class map(object)
 |  map(func, *iterables) --> map object
 |  Make an iterator that computes the function using arguments from
 |  each of the iterables.  Stops when the shortest iterable is exhausted.

简单解释下,map有需要两个参数func和iterables.可以这么理解,func是你根据需求编写的一个函数,iterables是你需要操作的一个可迭代对象,他们的返回值是一个iterator(迭代器),有关迭代器的概念这里不多讲,不过暂时可以简单的记住迭代器可以通过list(iterator)或者set(iterator)生成一个列表或者集合.

举个比较经典的例子吧,把一个数列a = [1,2,3,3,4,5,6]中的所有元素平方后生成一个新的数列b:

>>> a = [1,2,3,4,5,67]>>> def func(x):...  return x*x... >>> b=list(map(func,a))>>> b[1, 4, 9, 16, 25, 4489]>>> 

在这个例子中,假设你不清楚map用法也完全可以得到我们想要的结果b,不过那样的话你是不是至少用一个for循环呢,多谢几行代码呢?其实多写几行代码倒是没有什么,重点使用map起码能够给我们的代码增添一点点点的亮点。

class filter(object)
 |  filter(function or None, iterable) --> filter object
 |  Return an iterator yielding those items of iterable for which function(item)
 |  is true. If function is None, return the items that are true.

跟map一样需要两个参数func和可迭代对象,在filter执行过程中把iterable中的每一个元素迭代到func中,如果执行结果为真的把当前元素添加到迭代器中,当所有元素执行完后,返回迭代器.

看例子:

a=[4,5,6,7,8,9,0]>>> def dayu_5(x):...  if x>5:...   return True>>> list(filter(dayu_5,a))[6, 7, 8, 9]

sorted(iterable, key=None, reverse=False)
    Return a new list containing all items from the iterable in ascending order.

返回一个包含了所有可迭代对象,并且按照升序排列的一个新的列表

看例子:

>>> l=[2,34,5,61,2,4,6,89]>>> sorted(l)[-89, -6, 2, 2, 4, 5, 34, 61]>>> sorted(l,key=lambda x:abs(x))[2, 2, 4, 5, -6, 34, 61, -89]>>> sorted(l,key=lambda x:abs(x),reverse=True)[-89, 61, 34, -6, 5, 4, 2, 2]

#三个例子分别使用了sorted的默认排序,key自定义排序,以及reverse翻转的功能.

key其实表示的一个函数,接着看下面的例子:
>>> def ff(x):
...  return abs(x)
>>> sorted(l,key=ff,reverse=False)
[2, 2, 4, 5, -6, 34, 61, -89]
可以看到效果是一样的

 待续。。。。。

0 0
原创粉丝点击