def function(a):
def f1(a, b): a[b] = (a.get(b) or 0) + 1; return a
return map(lambda a: a[0], filter(lambda a: not a[1] == 1,
reduce(f1, a, {}).items()))
我已尝试打印此功能的返回值。当我为'a'分配一个数字时没有打印,如果我将一个字符串分配给'a',该函数返回一个由逗号分隔的随机字母列表。除此之外,我不确定发生了什么或为什么要打印这些字母。希望比我更聪明的人能够看到这一点,并了解正在发生的事情。
另外,这被认为是更高阶函数吗?
答案 0 :(得分:7)
此代码看起来有意混淆;希望它在生产中不存在。对变量名称的长度或行数没有征税。
那就是说,了解它你只需要将其分解一下。我们有:
return map(lambda a: a[0], # extract the first element
filter(lambda a: not a[1] == 1, # take iff second element != 1
reduce(f1, a, {}).items() # reduce a using f1, then take items()
)
)
因此,换句话说,结果将是通过运行reduce(f1, a, {})
构建的字典中的每个键,其对应值不是1
。
我们现在可以考虑这里实际发生了什么。
def f1(a, b):
a[b] = (a.get(b) or 0) + 1
return a
当作为参数传递给reduce
时,f1
的第一个参数将是正在构建的序列,第二个参数将是正在处理的项。
这里讨论的序列是一个字典(您可以从reduce
的参数以及在a.get
中使用f1
来判断。考虑到这一点:
def f1(a, b):
a[b] = (a.get(b) or 0) + 1 # increment value iff key present else value=1
return a # return mutated sequence
因此,运行reduce(f1, 'some_string', {})
的结果将是一个字典,将字符映射到字符串中的频率。
整个函数因此返回在字符串中出现多次的所有字母。
问题中的功能显然是一个人为的例子;考虑更好的方法来做到这一点是很简单的(地狱,很难想到更糟糕的)。
一种可能的解决方案,虽然绝不是最好的解决方案,但是会像:
freqs = lambda s: [c for c in set(s) if s.count(c) > 1]
或者,如果你真的喜欢使用map
和filter
,你可以这样做:
freqs = lambda s: filter(lambda count: count > 1, map(s.count, set(s))
老实说,这是一个案例,其中列表推导的python仍然 更具可读性;以上就像地狱一样拙劣和丑陋。