-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)と同様のことを行うこともできますが、要素とそのカウントのリストを維持し、reduce関数に追加することで、Counterクラスを使用する必要はありませんが、同じものの効率が低く、面倒なバージョンです。 。

フィルタとリデュースを使用する必要があるとおっしゃっているのでこれは宿題だと思います。これらはこの問題に対して絶対に間違ったツールであるため、これはばかげています。しかし、これは、この問題を解決するためにフィルターとリデュース(およびマップも)を使用するためのひどく非効率的で読みにくい方法です。これはおそらくインストラクターが探しているもののようです。

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で使用する必要があります。sumreduce(operator.add, ...)
  • つまり、 counts[x] = sum(1 for el in colors if el == x)同じ(悪い)アルゴリズムですが、100万倍読みやすく、起動時間がはるかに短くなります。
  • それでも、reduce/summapはへの呼び出しに置き換えることができますlen(filter(...))(Python 2を想定します。3つでfilterイテレータを返すため、実行する必要がありますがlen(list(filter(...)))、これは無駄です)。
  • colorsこれは、 1回だけではなく、各色に対して1回だけ完全なリストを通過します。これにより、考えられる結果の完全なリストがわからない場合は使用できなくなり、すべての場合で効率が大幅に低下します。

誰かが主張できる唯一の「利点」は、表示されない色のカウントが0であるということです。もちろん、これは他のソリューションでも簡単に行うことができます。

于 2013-02-07T01:03:12.740 に答える
-2

これが最も簡単な解決策になると思います。フィルタなどは使用していませんが、かなり賢い解決策のようです

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

タプルのリストではなく、dictを作成することもできます...使用するPythonインタープリターのバージョンによって異なります。

于 2013-02-07T01:29:30.387 に答える