作为对一个平时靠c++吃饭的程序员来说,偶尔也想写点python程序,要想写就得要学,要学就得要总结和关联,把要学的知识与已学的知识相关联起来,可以更快地学习和理解新的知识。
首先看一下reduce()函数吧,http://www.cnblogs.com/lonkiss/p/understanding-python-reduce-function.html 有对reduce()函数的详细介绍和使用说明,下面的python代码都是参考的这个页面上的。
reduce() 函数在 python 2 是内置函数, 从python 3 开始移到了 functools 模块。
官方文档是这样介绍的
reduce(...)
reduce(function, sequence[, initial]) -> valueApply a function of two arguments cumulatively to the items of a sequence,
from left to right, so as to reduce the sequence to a single value.
For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
((((1+2)+3)+4)+5). If initial is present, it is placed before the items
of the sequence in the calculation, and serves as a default when the
sequence is empty.从左到右对一个序列的项累计地应用有两个参数的函数,以此合并序列到一个单一值。
例如,reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) 计算的就是((((1+2)+3)+4)+5)。
如果提供了 initial 参数,计算时它将被放在序列的所有项前面,如果序列是空的,它也就是计算的默认结果值了
浓浓的熟悉味道,这不就是c++ stl里面的std::accumulate嘛,先写一段简单的代码看一下两者的对比。
先是python的:
def add(x, y):
return x+y
from functools import reduce
reduce(add, [1,2,3,4])
输出结果是10
看看c++的
int n[]={1, 2, 3, 4};
std::cout << std::accumulate(n, n+4, 0) << std::endl;
没有意外,也是10
其实这个例子并不好,因为在python中单纯的序列累加可以使用内置函数sum,而没有运算函数作为参数的std::accumulate函数也是完成的容器内元素的累加,从这一点上来说,不带运算函数参数的std::accumulate对应的应该是sum函数。
print(sum([1, 2, ,3 ,4]))
看一下std::accumulate的原型,有2个:
sum (1) | |
---|---|
custom (2) | |
很明显,sum函数对应的是第一个,reduce函数对应的是第二个。
来点复杂一点的分类,看一下reduce函数和std::accumulate函数是如何对应的,这里是按性别分类,程序只是演示用,python的:
from functools import reduce
scientists =({'name':'Alan Turing', 'age':105, 'gender':'male'},
{'name':'Dennis Ritchie', 'age':76, 'gender':'male'},
{'name':'Ada Lovelace', 'age':202, 'gender':'female'},
{'name':'Frances E. Allen', 'age':84, 'gender':'female'})
def group_by_gender(accumulator , value):
accumulator[value['gender']].append(value['name'])
return accumulator
grouped = reduce(group_by_gender, scientists, {'male':[], 'female':[]})
print(grouped)
输出:
{'male': ['Alan Turing', 'Dennis Ritchie'], 'female': ['Ada Lovelace', 'Frances E. Allen']}
用c++来模拟一下,好像不太好模拟,姑且这样吧
std::vector<std::map<std::string, std::string>> data = {
{{"name", "Alan Turing"}, {"gender", "male"}},
{{"name", "Dennis Ritchie"}, {"gender", "male"}},
{{"name", "Ada Lovelace"}, {"gender", "female"}},
{{"name", "Frances E. Allen"}, {"gender", "female"}}
};
std::map<std::string, std::vector<std::string>> output;
output = std::accumulate(data.begin(), data.end(), output,
[](std::map<std::string, std::vector<std::string>>& item1, std::map<std::string, std::string>& item2) -> std::map<std::string, std::vector<std::string>>& {
item1[item2["gender"]].push_back(item2["name"]);
return item1;
});
for (auto& val : output) {
std::cout << val.first << std::endl;
for (auto& str : val.second) {
std::cout << str << std::endl;
}
}
输出:
female
Ada Lovelace
Frances E. Allen
male
Alan Turing
Dennis Ritchie
这不,会了一个就会第二个了。