-2
c=["pink", "purple", "black", "yellow", "purple", "indego", "white", "peach"]
import random
import collections
def apply(T):
    i = random.randint(0, 7)
    return c[i]
for x in range(1, 50):
    for ch in map(apply, c):
        print(ch)

我试图弄清楚如何仅使用 filter 和 reduce 函数来计算每个数字的出现次数。

有人能指出我正确的方向吗?

编辑:为了澄清,我想计算生成某种类型的随机数的次数,而不是列表中的那个!

4

3 回答 3

2

首先,你的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/summap可以只被调用替换len(filter(...))(假设 Python 2;在三个中,filter返回一个迭代器,所以你必须这样做len(list(filter(...))),这是浪费的)。
  • 它为每种颜色传递colors一次完整列表,而不仅仅是一次。这使得在您不知道可能结果的完整列表的情况下无法使用,并且在所有情况下效率都低得多。

有人可以声称的唯一可能的“优势”是它对任何未出现的颜色都包含 0 计数。当然,这对于任何其他解决方案也是微不足道的。

于 2013-02-07T01:03:12.740 回答
0

@杜格尔

下面可以很好地使用 reduce 和 lambda 来计算列表:

    c = ["pink", "purple", "black", "yellow", "purple", "indego", "white", "peach", "test"]
    print reduce(lambda x, y: x + 1, c, 0)

注意 reduce() 的最后一个参数是 0。

于 2017-04-27T19:53:13.687 回答
-2

我认为这将是最简单的解决方案。它不使用过滤器左右,但它似乎很聪明的解决方案

counts = [(colors.count(x), x) for x in set(colors)]

您还可以制作字典,而不是元组列表...取决于您使用的 python 解释器版本。

于 2013-02-07T01:29:30.387 回答