Python中的Map Reduce问题
我现在在做一个作业,遇到了一些困难。这个作业需要读取一个txt文件,然后计算里面有多少个回文和它们出现的频率。我需要用Map Reduce来实现这个功能。
比如说,字符串“bab bab bab cab cac dad”应该输出:
bab 3
cab 1
dad 1
这是我目前的进展
def palindrome(string):
palindromes = []
for word in string.split(" "):
if (word == word[::-1]):
palindromes.append(word)
return palindromes
string = "abc abd bab tab cab tat yay uaefdfdu"
print map(lambda x: palindrome(x), ["bab abc dab bab bab dad crap pap pap "])
现在打印的结果是
[['bab', 'bab', 'bab', 'dad', 'pap', 'pap', '']]
这是我在reduce部分的尝试
def p(lists):
for list in lists:
set_h = set(list)
return set_h
我想用p函数创建一个包含所有找到的回文的集合。然后对这个列表中的回文进行计数,并把结果做成一个字典。
print reduce(p, [['bab', 'bab', 'bab', 'dad', 'pap', 'pap', '']])
我这样做对吗?
5 个回答
对于你的reduce函数,首先应该从一个空字典开始,然后更新或填充你的计数。reduce函数需要两个参数,一个可以是你的字典,另一个是你的回文字符串。你可以像这样在reduce中输入一个初始值:
reduce(lambda x, y: x+y, some_list, initial_value_for_x)
可以看看字典的get方法,了解如何设置默认值,这样可以帮助你大大简化你的reduce函数。
我觉得如果你的 map()
和 reduce()
的输入是一个实际的单词列表,那会简单很多。为了做到这一点,你可以先用 .split()
方法把字符串分割成单词,然后再传给 map()
。接着,map()
可以把每个单词处理成它自己(如果这个单词是回文的话),或者变成 None
。之后,你可以用 filter()
来过滤掉那些 None
的结果,接着对剩下的结果进行排序,然后传给 reduce()
。最后,reduce()
会把这些结果合并成一个 dict
,这个字典会把单词和它们的总出现次数对应起来。
我不会给你一个完整的解决方案,因为我不想影响你的学习过程。
在你使用 map() 之前,先把字符串分割成一个列表。因为 map() 是用来处理列表、集合和字典的,而不是字符串。
word_list = words_str.split(" ")
除非作业要求你这样做,否则尽量不要使用 map-filter-reduce;GVR 也这么说过。正确的做法是使用 Python 的 列表推导 语法。实际上,你可以用一个很简洁的单行代码来实现:
pal_count = {
x: word_list.count(x) # reduce-ish
for x in word_list # map-ish
if x == x[::-1] # filter-ish
}
for x, y in pal_count.iteritems():
print x, y # print the results!
我们来分解一下这个过程...
- 先把结果放到一个字典对象里,以便后面打印:
pal_count = {
- 定义返回的对象:
x: word_list.count(x)
这里我们用键值对的方式,把回文字符串 x 和它出现的次数关联起来。count() 就像是一个内置的列表减少函数。 - 用一个 for 循环 遍历我们的列表,把当前值赋给 'x':
for x in word_list
- 我们只想返回回文字符串,所以需要加一个比较操作符来 过滤 不合格的值:
if x == x[::-1] # 这个逻辑很酷哦
- 太好了!
}
顺便说一下,我之所以帮你做作业,是因为我从来没有做过我的作业。
相对来说,慢一些、灵活性差、可移植性差、也不那么 酷 的做法是使用嵌套的 for 循环:
pal_count = dict()
for x in word_list: # same loop
if x == x[::-1] # is this a palindrome?
if x in pal_count: # have we seen before?
pal_count[x] += 1
else: # this one is new!
pal_count.setdefault(x, 1)