python-----Advanced Iterators
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python-----Advanced Iterators相关的知识,希望对你有一定的参考价值。
python笔记--9.5
map/reduce
map()和reduce()均为Python内置的函数
map()函数接受两个参数,一个是函数,一个是Iterable。map将传入的函数一次作用到序列的每一个元素,并把结果作为新的Iterator返回。
例如:
def f(x):
return x*x
r=map(f,[1,2,3,4,5,6,7,8,9])
print(list(r))
result:
[1,4,9,16,25,36,49,64,81]
又如:
print(list(map(str,[1,2,3,4,5,6,7,8,9])))
result:
[‘1‘,‘2‘,‘3‘,‘4‘,‘5‘,‘6‘,‘7‘,‘8‘,‘9‘]
reduce()把一个函数作用在一个序列[x1,x2,x3,...]上,这个函数接收两个参数,reduce把结果继续和序列的下一个元素做累积运算。
如:
reduce(f,[x1,x2,x3,x4])=f(f(f(x1,x2),x3),x4)
需求1:将[1,2,3,4,5]转化成12345输出
from functools import reduce
def fn(x,y):
return 10*x+y
reduce(fn,[1,2,3,4,5])
需求2:将字符串‘13579’转换成数字13579输出
from functools import reduce
def str2int(s):
def fn(x,y):
return x*10+y
def char2num(s):
retuen return {‘0‘: 0, ‘1‘: 1, ‘2‘: 2, ‘3‘: 3, ‘4‘: 4, ‘5‘: 5, ‘6‘: 6, ‘7‘: 7, ‘8‘: 8, ‘9‘: 9}[s]
return reduce(fn,map(char2num,s))
需求3:将字符串‘123.456’转换成123.456
def str2float(s):
def fn(x,y):
return x*10+y
def fx(x,y):
return x/10+y
def char2num(s):
return {‘0‘:0,‘1‘:1,‘2‘:2,‘3‘:3,‘4‘:4,‘5‘:5,‘6‘:6,‘7‘:7,‘8‘:8,‘9‘:9}[s]
L=s.split(‘.‘,1)
return reduce(fn,map(char2num,L[0]))+reduce(fx,map(char2num,L[1][-1::-1]))/10
----------------------------------------------------------------------------------------------------------------
生成表达式(Generator Expression)
像是一个生成函数,但是不是函数
unique_characters={‘E‘,‘D‘,‘M‘,‘O‘,‘N‘,‘S‘,‘R‘,‘Y‘}
gen=(ord(c) for c in unique_characters)
next(gen)#69
next(gen)#68
tuple(ord(c) for c in unique_characters)
print(tuple)#(69,68,77,79,78,83,82,89)
使用生成函数完成相同任务:
def ord_map(a_string):
for c in a_string:
yield ord(c)
gen=ord_map(unique_characters)
---------------------------------------------------------------------------------
排列组合问题的计算:
import itertools
在itertools中包含很多有意思的东西,permutations()就是包括在其中的寻找所有排列组合的有趣的方法
import itertools
perms=itertools.permutations([1,2,3],2)
next(perms)#(1,2)
next(perms)#(1,3)
next(perms)#(2,1)
next(perms)#(2,3)
next(perms)#(3,1)
next(perms)#(3,2)
permutations()接收两个参数,一个是一个序列,一个是一个int整数,表示在每个组合中你想要的元素的个数
permutations()接收的不一定必须是一个list,可以是任意序列,甚至可以是一个string
例如:
import itertools
perms=itertools.permutations(‘ABC‘,3)
print(list(perms))
‘‘‘
[
(‘A‘,‘B‘,‘C‘),(‘A‘,‘C‘,‘B‘),
(‘B‘,‘A‘,‘C‘),(‘B‘,‘C‘,‘A‘),
(‘C‘,‘A‘,‘B‘),(‘C‘,‘B‘,‘A‘)
]
‘‘‘
----------------------------------------------
在itertools模块中的另一个有趣的方法
import itertools
list(itertools.product(‘ABC‘,123‘))
[
(‘A‘, ‘1‘), (‘A‘, ‘2‘), (‘A‘, ‘3‘),
(‘B‘, ‘1‘), (‘B‘, ‘2‘), (‘B‘, ‘3‘),
(‘C‘, ‘1‘), (‘C‘, ‘2‘), (‘C‘, ‘3‘)
]
list(itertools.combinations(‘ABC‘,2))
[(‘A‘,‘B‘),(‘A‘,‘C‘),(‘B‘,‘C‘)]
-------------------------------------------------
引例:
names=list(open(‘favorite-people.txt‘,encoding=‘utf-8‘))
print(names)
[‘Dora\n‘, ‘Ethan\n‘, ‘Wesley\n‘, ‘John\n‘, ‘Anne\n‘,
‘Mike\n‘, ‘Chris\n‘, ‘Sarah\n‘, ‘Alex\n‘, ‘Lizzie\n‘]
list(open(filename))将会以list的形式返回文本文件中的每一行数据,但是‘\n‘也包含在其中一起返回
使用rstrip()方法可以去掉尾部的‘\n‘
names=[name.rstrip() for name in names]
print(names)
[‘Dora‘, ‘Ethan‘, ‘Wesley‘, ‘John‘, ‘Anne‘,
‘Mike‘, ‘Chris‘, ‘Sarah‘, ‘Alex‘, ‘Lizzie‘]
使用sorted()方法可以对list进行排序,默认按照字母表顺序排序
names=sorted(names)
print(names)
[‘Alex‘, ‘Anne‘, ‘Chris‘, ‘Dora‘, ‘Ethan‘,
‘John‘, ‘Lizzie‘, ‘Mike‘, ‘Sarah‘, ‘Wesley‘]
sorted()方法可以接收一个用于指示排序方法的key参数
names=sorted(names,key=len)
print(names)
[‘Alex‘, ‘Anne‘, ‘Dora‘, ‘John‘, ‘Mike‘,
‘Chris‘, ‘Ethan‘, ‘Sarah‘, ‘Lizzie‘, ‘Wesley‘]
即按照名字长短进行排序
那么如何使用itertools来实现相同的操作?
import itertools
groups=itertools.groupby(names,len)
itertools.groupby方法接收两个参数,一个序列和一个key方法,并且返回一个生成组对的迭代器(iterator)。每个组对(pair)包含
key_function(each item)的结果和另一个迭代器(包含所有有相同key值的元素)
list(groups)操作可得到结果如下:
[(4, <itertools._grouper object at 0x00BA8BF0>),
(5, <itertools._grouper object at 0x00BB4050>),
(6, <itertools._grouper object at 0x00BB4030>)]
下面我尝试来遍历:
groups=itertools.groupby(name,len)
for name_length,name_iter in groups:
print(‘Names with {0:d} letters:‘.format(name_length))
for name in name_iter:
print(name)
可以得到如下结果:
Names with 4 letters:
Alex
Anne
Dora
John
Mike
Names with 5 letters:
Chris
Ethan
Sarah
Names with 6 letters:
Lizzie
Wesley
注意:itertools.groupby()方法只有在输入的序列已经被排序后才有效,比如在此例中用len进行分组可行是因为在之前我们已经对names进行了
sorted(names,key=len)
----------------itertools.chain()-------------------------------------
list(range(0,3))#[0,1,2]
list(range(10,13))#[10,11,12]
list(itertools.chain(range(0,3),range(10,13)))#[0,1,2,10,11,12]
itertools.chain()方法可以接收任意数量的迭代器,可以把他们按照传入的顺序连接起来
-------------zip()--------------------------------------------
list(zip(range(0,3),range(10,13)))#[(0,10),(1,11),(2,12)]
list(zip(range(0,3),range(10,13),range(20,23)))#[(0, 10, 20), (1, 11, 21), (2, 12, 22)]
zip()方法接收任意数量的序列,返回所有序列的第一个元素构成的元组,第二个元素构成的元组.....
list(zip(range(0, 3), range(10, 14))) #[(0,10),(1,11),(2,12)]
zip()方法在最短的序列结束时停止,如上例所述。
list(itertools.zip_longest(range(0,3),range(10,14))) #[(0, 10), (1, 11), (2, 12), (None, 13)]
但是itertools.zip_longest()方法在最长序列结束后结束,短序列没有值与之对应的用None填充
-------------------------------alphametics solver(算术谜题解法)------------------------------------
characters=(‘S‘, ‘M‘, ‘E‘, ‘D‘, ‘O‘, ‘N‘, ‘R‘, ‘Y‘)
guess=(‘1‘, ‘2‘, ‘0‘, ‘3‘, ‘4‘, ‘5‘, ‘6‘, ‘7‘)
tuple(zip(characters,guess))
返回结果:
((‘S‘, ‘1‘), (‘M‘, ‘2‘), (‘E‘, ‘0‘), (‘D‘, ‘3‘),
(‘O‘, ‘4‘), (‘N‘, ‘5‘), (‘R‘, ‘6‘), (‘Y‘, ‘7‘))
dict(zip(character,guess))
返回结果:
{‘E‘: ‘0‘, ‘D‘: ‘3‘, ‘M‘: ‘2‘, ‘O‘: ‘4‘,
‘N‘: ‘5‘, ‘S‘: ‘1‘, ‘R‘: ‘6‘, ‘Y‘: ‘7‘}
算术谜题解法使用了这种技术来创建一个字典将puzzle里面的字母映射为解决方案里的数字。
characters=tuple(ord(c) for c in sorted_characters)
digits=tuple(ord(c) for c in ‘0123456789‘)
...
for guess in itertools.permutations(digits,len(characters)):
...
equation=puzzle.translate(dict(zip(characters,guess)))
-------------下面先解释一下translate()方法-----------------------------
在Python中strings有许多种方法,包括lower(),count(),format()等,现在想要介绍一种很少见但功能强大的方法:translate()
translate_table={ord(‘A‘):ord(‘O‘)}
print(translate_table) #{65:79}
‘MARK‘.translate(translate_table) #‘MORK‘
字符串的转换方法需要一个转换表(translate_table),就是将一个字符映射为另一个字符的字典,当然说字符并不是很准确,应该说是byte
bytes在Python3中是整形(integer),ord()方法返回一个字符的ASCII值(A-Z:65-90)
作用在字符串上的translate()方法接受一个转换表(translate_table),并将该字符串在该表中进行运行,替换掉所有在转换表中出现过的key
值,替换为其对应的值。(本例中,translate MARK to MORK)
-------------------------------------------------------------
这与解决字母算术难题有什么关系吗?请看如下:
characters=tuple(ord(c) for c in ‘SMEDONRY‘)
print(character) #(83, 77, 69, 68, 79, 78, 82, 89)
guess=tuple(ord(c) for c in ‘91570682‘)
print(guess) #(57, 49, 53, 55, 48, 54, 56, 50)
translate_table=dict(zip(character,guess))
print(translate_table) #{68: 55, 69: 53, 77: 49, 78: 54, 79: 48, 82: 56, 83: 57, 89: 50}
‘SEND+MORE==MONEY‘.translate(translate_table) #‘9567+1085==10652‘
-----------------------将任意字符串作为Python表达式求值---------------------------------
eval(‘1+1==2‘)#True
eval(‘1+1=3‘)#False
eval(‘9576+1085==10652‘)#True
eval()方法远不止于布尔型的表达式
eval(‘"A"+"B"‘)#‘AB‘
eval(‘"Mark".translate({65:79})‘)#MORK
eval(‘"AAAAA".count("A")‘)#5
eval(‘["*"]*5‘)#[‘*‘,‘*‘,‘*‘,‘*‘,‘*‘]
x=5
eval(‘x*5‘)#25
eval(‘pow(x,2)‘)#25
import math
eval(‘math.sqrt(x)‘)#2.2360679774997898
-----------------------------------------how to solve alphametic puzzles-------------------------------------------
1,find all letters in the puzzle :re.findall(),return a list
2,find all the unique letters in the puzzle:with sets and the set()function,return a set;with ‘‘.join()function join words
together;with set()to get seperate letters
3,check if there are more than 10 unique letters:with an assert statement(meaning that the puzzle if definitely unsolvable)
4,Convert the letters to their ASCII equivalents:with a generator object(unique_character={ord(c) for c in unique_characters})
5,calculates all the possible solutions:with the itertools.permutation()function
6,convert each possible solution to a Python expression:with translate()string method
7,test each possible solution by evaluating the Python expression:with eval()function
8,return the first solution that evaluates to True
---------------------codes----------------------------------------------
import re
import itertools
def solve(puzzle):
words = re.findall(‘[A-Z]+‘, puzzle.upper())
unique_characters = set(‘‘.join(words))
assert len(unique_characters) <= 10, ‘Too many letters‘
first_letters = {word[0] for word in words}
n = len(first_letters)
sorted_characters = ‘‘.join(first_letters) + \
‘‘.join(unique_characters - first_letters)
characters = tuple(ord(c) for c in sorted_characters)
digits = tuple(ord(c) for c in ‘0123456789‘)
zero = digits[0]
for guess in itertools.permutations(digits, len(characters)):
if zero not in guess[:n]:
equation = puzzle.translate(dict(zip(characters, guess)))
if eval(equation):
return equation
if __name__ == ‘__main__‘:
import sys
for puzzle in sys.argv[1:]:
print(puzzle)
solution = solve(puzzle)
if solution:
print(solution)
以上是关于python-----Advanced Iterators的主要内容,如果未能解决你的问题,请参考以下文章