当前位置: 代码迷 >> 综合 >> Python cookbook container second
  详细解决方案

Python cookbook container second

热度:75   发布时间:2023-11-05 19:34:01.0

11命名切片

问题:你的程序已经出现一大堆已无法直视的硬编码切片下标,然后你想清理下代码

要从一个记录字符串中几个固定位置提取出去特定的数据字段

slice(23,34)放到[]中就是切片的意思,内置的slice()函数创建了一个切片对象,可以被用在任何切片允许使用的地方,string,list,tuple..

slice() s.start s.stop s.step 属性来获取其信息

indices(size)方法将其映射到一个确定大小的序列,返回一个三元组 (start,stop,step),所有的值都会被相应的缩小以满足边界限制

s='HelloWorld'
a.indices(len(s))
for i in range(*a.indices(len(s))):print(s[i])

12序列中出现最多的元素

collections.Counter类直接就是为这类问题而设计的,作为输入,Counter对象可以接受任意的hashable序列对象,一个Counter对象就是一个字典 {字符:次数}

words=['look','into','my','eyes','look','into','my','eyes','the','eyes','the','eyes','the','eyes','not','around','the','eyes',"don't",'look','around','the','eyes','look','into','my','eyes',"you're",'under']
from collections import Counter
word_count=Counter(words)
three_top=word_count.most_common(3)
word_count['not']

Counter实例的特性就是它们很容易的跟数学运算操作相结合..

13通过某个关键字排序一个字典列表

使用operator 模块的itemgetter函数

rows=[{'frame':'Brian','lname':'Jones','uid':1003},{'frame':'David','lname':'Beazley','uid':1002},{'frame':'John','lname':'Cleese','uid':1001},{'frame':'Big','lname':'Jones','uid':1004},
]
from operator import itemgetter
rows_by_fname=sorted(rows,key=itemgetter('frame'))
rows_by_uid=sorted(rows,key=itemgetter('uid'))
rows_by_both=sorted(rows,key=itemgetter('frame','uid'))
print(rows_by_fname)
print(rows_by_uid)

14排序不支持原生比较的对象

问题:你想排序类型相同的对象,但是它们不支持原生的比较操作

解决方案:内置的sorted函数有一个关键字key,可以传入一个callable对象给它,这个callable对象对每个传入的对象返回一个值,这个值会被sorted用来排序这些对象

class User:def __init__(self,user_id):self.user_id=user_iddef __repr__(self):return 'User({})'.format(self.user_id)def sort_notcopare():users=[User(34),User(12),User(23)]print(users)print(sorted(users,key=lambda k:k.user_id))
sort_notcopare()
from operator import attrgetter
users=[User(34),User(12),User(23)]
sorted(users,key=attrgetter('user_id'))

这里的__repr__有点像Java 的toString

选择使用lambda函数或者attrgetter()可能取决于个人喜好,但是 ,attrgetter()函数通常会运行的快点,并且还能同时允许多个字段进行比较...

min(users,key=attrgetter('user_id'))

15通过某个字段将记录分组

问题:字典或者实例的序列,然后你想根据某个特定的字段比如date来分组迭代访问..itertools.groupby()函数对于这样的数据分组操作非常实用..

rows=[{'address':'5412 N CLARK','date':'07/01/2012'},{'address':'5418 N CLARK','date':'07/04/2012'},{'address':'5412 E 58th','date':'07/02/2012'},{'address':'2122 N CLARK','date':'07/03/2012'},{'address':'5465 N ravenswood','date':'07/02/2012'},{'address':'1060 W ADDISON','date':'07/02/2012'},{'address':'4801 N BROADWAY','date':'07/01/2012'},{'address':'1039 W GRANVILLE','date':'07/04/2012'},
]
from operator import itemgetter
from itertools import groupby
rows.sort(key=itemgetter('date'))#groupby只能将临近的分组出来,也就是排好序的..
for date,items in groupby(rows,key=itemgetter('date')):print(date)for i in items:print(' ',i)rows=[{'address':'5412 N CLARK','date':'07/01/2012'},{'address':'5418 N CLARK','date':'07/04/2012'},{'address':'5412 E 58th','date':'07/02/2012'},{'address':'2122 N CLARK','date':'07/03/2012'},{'address':'5465 N ravenswood','date':'07/02/2012'},{'address':'1060 W ADDISON','date':'07/02/2012'},{'address':'4801 N BROADWAY','date':'07/01/2012'},{'address':'1039 W GRANVILLE','date':'07/04/2012'},
]
from operator import itemgetter
from itertools import groupby
from collections import defaultdict
row_by_date=defaultdict(list)
for date,items in groupby(rows,key=itemgetter('date')):for i in items:row_by_date[date].append(i)
print(row_by_date)

16过滤序列元素:

问题:你有个数据序列,想利用一些规则从中提取出有用的值

values=['1','2','3','-','4','N/A','5']
def is_int(val):try:x=int(val)return Trueexcept ValueError:return False
ivals=list(filter(is_int,values))
print(ivals)
genetor 的写法在这里体现出来了...将''转化成int,return的值是Boolean
list(filter(lambda k:k>0,mylist))address={'5412 N CLARK','5418 N CLARK','5412 E 58th','2122 N CLARK','5465 N ravenswood','1060 W ADDISON','4801 N BROADWAY','1039 W GRANVILLE'}
counts=[0,3,10,4,1,7,6,1]
from itertools import compress
more5=[n>5 for n in counts]
list(compress(counts,more5))

另一个过滤工具就是itertools.compress(),它以一个iterable对象和一个相对应的Boolean选择对象序列返回作为输入参数,然后输出iterable对象里面对应选择器为True的对象

[n>5 for n in nums]返回的是Boolean  ,,

17从字典中提取子集:

问题:这个有点像数分,可以将转化成dataframe 然后取出来...这里采用的是最基本的

prices={'ACME':45.23,'AAPL':612.78,'IBM':205.55,'HPQ':37.20,'FB':10.75
}
p1={key:value for key,value in prices.items() if value>200}
tech_name={'AAPL',"IBM",'HPQ',"MSFT"}
p2={key:value for key,value in prices.items() if key in tech_name}
p3={key:prices[key] for key in prices.keys() &tech_name}
print(p1,p2,p3)

18映射名称到序列元素

不想通过下标,想通过名称来访问list

作用:让代码表意清晰:也支持普通的tuple支持的特性,解压和索引

from collections import namedtuple
Stock=namedtuple('Stock',['name','shares','prices'])
def compute_records(records):totals=0.0for rec in records:s=Stock(*rec)totals+=int(s.shares)*int(s.prices)return totals

命名元组实例的_replace()方法,定义一个需要更新很多实例属性的高效数据结构,命名元组就不是最佳选择,需要定义一个包含__slots__()方法的类???(下面会描述)

9转换并同时转换数据:

需要在数据序列上执行聚集函数(比如sum min max等),但是需要先转换或者过滤函数...

解决方法:使用一个生成器表达参数..

nums=[1,2,3,4,5,6]
s=sum(n**2 for n in nums)import os 
files=os.listdir(r'C:\Users\win10\begin')
if any(name.endswith('ipynb') for name in files):print('there be python')
else:print('sorry ,no python')
portfolio=[{'name':'Good','shares':50},{'name':'YHOO','shares':75},{'name':'AOL','shares':20},{'name':'SCOX','shares':65},]
p_min=min(s['shares'] for s in portfolio)
p_min=min(portfolio,key=lambda x:x['shares'])

其中,s=sum(n**2 for n in nums)这个可以达到目的的也可以用sum([n**2 for n in nums])但是会额外的创建一个列表,而生成器方案会以迭代的方式处理数据,会更省内存

10合并多个字典或者映射:

一个ChainMap函数只是提供了一个新的内存将两个字典放进去,然后提供一些常用的字典的操作,比如删除,add_child等...

a={'x':1,'y':2}
b={'z':3,'y':4}
l=dict(a)
l.update(b)
print(l)a={'x':1,'y':2}
b={'z':3,'y':4}
from collections import ChainMap
c=ChainMap(a,b)
print(c)

所以说update是一次性的买卖,ChainMap是多次的,更加适合global类型的数据......并且对两个字典进行操作,影响大的是第一个....

chapter 2,p44

  相关解决方案