首先,你的apply
函数忽略了它的参数,这对于你正在给予的东西来说从来都不是一个好兆头map
。我将假设您正在尝试生成一个随机颜色列表,称为colors
,然后计算它;你同样可以用发电机代替它。
Filter、reduce 等是函数式编程概念,通常通过 Python 中的列表推导或生成器更好地处理。这是我的做法:
c = ["pink", "purple", "black", "yellow", "purple", "indego", "white", "peach"]
import random
colors = [c[random.randrange(len(c))] for _ in range(50)]
# now, to count
# (a) the way you'd actually do it in practice:
from collections import Counter
counts = Counter(colors)
# (b) the way you'd actually do it without the collections module
counts = {}
for x in colors:
if x not in counts:
counts[x] = 0
counts[x] += 1
# (c) doing it with reduce...technically.
def add_to_counter(counter, el):
counter[el] += 1 # can't actually do this in a lambda...
counts = reduce(add_to_counter, colors, Counter())
您也可以做类似于 (c) 的事情,但不只是使用 Counter 类,方法是维护一个元素列表及其计数,并在 reduce 函数中添加它们,但这只是同一件事的效率较低且更麻烦的版本.
既然你说你必须使用过滤器和减少,我假设这是一个家庭作业。这很愚蠢,因为这些绝对是解决这个问题的错误工具。但这是一种使用过滤器和减少(以及映射)来解决这个问题的非常低效且不可读的方法,这可能就像您的讲师正在寻找的那样:
from functools import partial
import operator
counts = {}
for x in c:
counts[x] = reduce(operator.add,
map(lambda _: 1, filter(partial(operator.eq, x), colors)),
0)
这很可怕,因为:
- 弄清楚发生了什么需要付出很多努力,而不是上面(a)和(b)的显而易见性。
- 您应该始终在 Python 中使用
sum
,而不是reduce(operator.add, ...)
.
- 所以,
counts[x] = sum(1 for el in colors if el == x)
是相同的(坏的)算法,但可读性提高了一百万倍,启动时间短得多。
- 即便如此,
reduce
/sum
和map
可以只被调用替换len(filter(...))
(假设 Python 2;在三个中,filter
返回一个迭代器,所以你必须这样做len(list(filter(...)))
,这是浪费的)。
- 它为每种颜色传递
colors
一次完整列表,而不仅仅是一次。这使得在您不知道可能结果的完整列表的情况下无法使用,并且在所有情况下效率都低得多。
有人可以声称的唯一可能的“优势”是它对任何未出现的颜色都包含 0 计数。当然,这对于任何其他解决方案也是微不足道的。