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