0

ワンライナーでユニークな数字を効率的に数える方法を探しています。

例:整数を指定する623562と、戻り値はになります4

私の現在のやり方は、整数が与えられた場合i、imを使用することlen(set(str(i)))です。セットの作成には時間がかかります。私はたくさんの数字を調べているので、効率的な方法が必要です。

また、誰かがx使用せずに range()(そして1つのライナーで..)数字ですべての数字を調べる方法を見つけることができれば、私はうれしいです。リストが作成されるため、使用時にメモリが制限されますrange(私は推測します)。

4

3 に答える 3

11

setは、この作成用に最適化されています。独自の10進数から文字列への変換を展開する場合を除いて(複数行かかる場合)、それが最善の方法です。

rangePython2.xでのみメモリを割り当てます。623562のよ​​うな小さな数の場合、メモリは問題になりません。数値が大きい場合はxrange、Python 2.xで使用するか、Python 3.xに切り替えるrangeだけで、ちょうどいいタイミングで数値が生成されます。

于 2012-05-25T10:12:13.700 に答える
2

私はlen(set(str(num)))あなたにとって十分に速くないことを信じるのに苦労しています。len(set(str()))これは、ランダムで非常に大きな数の100,000回を実行するテストです。

% python -m timeit -s 'import random' 'for i in range(100000): \
  len(set(str(random.randint(199123212312399956789, 1000000099999999123091230000000))))'
10 loops, best of 3: 456 msec per loop

そして、その時間のまともなチャンクは、乱数を生成しているだけです!それよりも速く進む必要がある場合は、別の言語を検討する必要があると思います。

于 2012-05-25T10:38:11.630 に答える
1

毎回セットを作成しないようにする方法は次のとおりです。最後の行を除くすべてが初期化コードであるため、1回だけ発生します。

>>> from operator import or_
>>> from collections import Counter
>>> from functools import reduce
>>> bits = {str(i):2**i for i in range(10)}
>>> counts = [Counter(format(i,'b'))['1'] for i in range(2**10)]

>>> counts[reduce(or_, (bits[c] for c in str(623562)))]
4

ただし、単純で明確な明白なものよりも約3倍遅くなりますlen(set(str(i)))。Pythonではいつものように、物事をより複雑にしたり、過度に賢くしようとしたりすると、戻ってきてパフォーマンスに影響を与えます。

于 2012-05-25T10:48:39.053 に答える