要求,实现以下功能的函数:
- myfunc([2,3,4,5,12,13,14,15,16,20])
- returns:
- [(2,5),(12,16),20]
如果让我来实现,实现的方式注定比较笨一些,可能也就类似C语言的遍历判断了,不过在stackoverflow上有人给出了这样的答案:
- from operator import itemgetter
- from itertools import groupby
- data = [2,3,4,5,12,13,14,15,16,20]
- for k,g in groupby(enumerate(data),lambda(i,x):i - x):
- print map(itemgetter(1),g)
- output:
- [2,3,4,5]
- [12,13,14,15,16]
- [20]
里面涉及到不少之前没见过的python特性,慢慢分析:
1、enumerate
用于对一个列表或数组既需要遍历索引又要遍历元素时,会这样写:
- for i in range(0.len(list)):
- print i,list[i]
- '''使用enumerate关键字后'''
- for index,text in enumerate(list):
- print index,text
在cookbook里介绍,如果你要计算文件的行数,可以这样写:
- count = len(open(file,'ru').readlines)
- '''这种方法在遇到文件比较大时会很慢甚至不能工作,因此'''
- count = -1
- for count,line in enumerate(open(file,'ru')):
- pass
- count += 1
2、groupby
groupby位于python的itertools内,它的典型调用形式如下
- from itertools import groupby
- groupby(iterable[,key])
它接收一个可迭代的序列,以及一个比较函数key,它返回一个生成二元组的迭代器,每一个二元组包含key(each item)的结果和另一个包含着所有共享这个key结果的元素的迭代器。
通常情况下,这个可迭代的序列需要保证在相同的key function下已经有序,groupby的这类操作类似于unix系统中的uniq函数调用。
举一个例子:
- names = ['Alex','Anne','Chris','Ethan','Wesley']
- '''通过groupby把names中的元素以len长度进行分组,长度相等的位于一组'''
- groups = groupby(names,len)
- for name_length,name_iter in groups:
- print 'name with %d letters:' %name_length
- for name in name_iter:
- print name
- output:
- name with 4 letters:
- Alex
- Anne
- name with 5 letters:
- Chris
- Ethan
- name with 6 letters:
- Wesley
当然了,这个key function可以更加复杂,比如文章开头例子中的key = lambda(i,x): i - x,其利用学历的序号的自增,保证连续的数字拥有相同的(数字、序号)差,从而完成分组的目的
3、itemgetter(item[,args])
对于这个特性,举个例子应该更容易明白:
- from operator import itemgetter
- >>>itemgetter(1)('ABCD')
- 'B'
- >>>itemgetter(1,3,5)('ABCDEFG')
- ('B','D','F')
- >>>inventory = [('apple',3),('banana',2),('pear',5),('orange',1)]
- >>>getcount = itemgetter(1)
- >>>map(getcount,inventory)
- [3,2,5,1]
- >>>sorted(inventory,key = getcount)
- [('orange',1),('banana',2),('apple',3),('pear',5)]
- '''最后一个sorted类似于平时常用的按指定列排序'''
- >>>sorted(inventory,ken = lambda x:x[1])
4、to be continue...
阅读(773) | 评论(0) | 转发(0) |