2

各カウンターがファイルの種類 (.wav、.mp3 など) の発生をカウントしている一連のカウンターを格納するために辞書を使用しています。

filetypecounter = {}

特定のファイルの種類に遭遇したとき、pythonic の方法でカウンターを増やすことができるようにしたいと考えています。だから私は考えています...

filetypecounter[filetype] +=1

ただし、ファイルタイプがディクショナリにない場合は、インスタンス化して 1 にします。したがって、私のロジックは、ファイルタイプ カウンターが存在する場合は、カウンター値に 1 を追加し、それ以外の場合は 1 に設定します。

if filetype not in filetypecounter:
    filetypecounter[filetype] = 1
else: 
    filetypecounter[filetype] +=1

もっとpythonicな方法はありますか?

4

7 に答える 7

3
from collections import defaultdict

filetypecounter = defaultdict(int)
filetypecounter[filetype] += 1

また

from collections import Counter

filetypecounter = Counter()
filetypecounter.update([filetype])

情報については、を使用する必要がある場合dict、解決策(キーが存在するかどうかを確認する)は合理的なものです。おそらく、より「pythonic」なソリューションは次のようになります。

filetypecounter = {}
filetypecounter[filetype] = filetypecounter.get(filetype, 0) + 1

ただし、実際には、これと他の提案は同じテーマのバリエーションにすぎません。私ならカウンターを使います。

于 2013-02-23T20:25:41.010 に答える
2

よく使うことcollections.Counterは、この回答グループで十分にカバーされていますが、それは最速の選択ではないかもしれません.

1 つの古い方法は次のとおりです。

>>> d={}
>>> for ext in ('.mp3','.mp3','.m4a','.mp3','.wav','.m4a'):
...    d[ext]=d.setdefault(ext,0)+1
... 
>>> d
{'.mp3': 3, '.wav': 1, '.m4a': 2}

それも最速ではありませんが、それよりも高速ですcollections.Counter

これらのメソッドのベンチマークがあり、defaultdict、try/except、または元のメソッドのいずれかが最速です。

ここでベンチマークを再現 (および拡張) しました。

import urllib2
import timeit

response = urllib2.urlopen('http://pastebin.com/raw.php?i=7p3uycAz')
hamlet = response.read().replace('\r\n','\n')
LETTERS = [w for w in hamlet]
WORDS = hamlet.split(' ')
fmt='{:>20}: {:7.4} seconds for {} loops'
n=100
print
t = timeit.Timer(stmt="""
        counter = defaultdict(int)
        for k in LETTERS:
            counter[k] += 1 
        """,
        setup="from collections import defaultdict; from __main__ import LETTERS")

print fmt.format("defaultdict letters",t.timeit(n),n)
t = timeit.Timer(stmt="""
        counter = defaultdict(int)
        for k in WORDS:
            counter[k] += 1 
        """,
        setup="from collections import defaultdict; from __main__ import WORDS")

print fmt.format("defaultdict words",t.timeit(n),n)
print

# setdefault
t = timeit.Timer(stmt="""
        counter = {}
        for k in LETTERS:
            counter[k]=counter.setdefault(k, 0)+1
        """,
        setup="from __main__ import LETTERS")
print fmt.format("setdefault letters",t.timeit(n),n)
t = timeit.Timer(stmt="""
        counter = {}
        for k in WORDS:
            counter[k]=counter.setdefault(k, 0)+1
        """,
        setup="from __main__ import WORDS")
print fmt.format("setdefault words",t.timeit(n),n)
print

# Counter
t = timeit.Timer(stmt="c = Counter(LETTERS)",
        setup="from collections import Counter; from __main__ import LETTERS")

print fmt.format("Counter letters",t.timeit(n),n)
t = timeit.Timer(stmt="c = Counter(WORDS)",
        setup="from collections import Counter; from __main__ import WORDS")
print fmt.format("Counter words",t.timeit(n),n)
print

# in
t = timeit.Timer(stmt="""
        counter = {}
        for k in LETTERS:
            if k in counter: counter[k]+=1
            else: counter[k]=1   
        """,
        setup="from __main__ import LETTERS")
print fmt.format("'in' letters",t.timeit(n),n)
t = timeit.Timer(stmt="""
        counter = {}
        for k in WORDS:
            if k in counter: counter[k]+=1
            else: counter[k]=1   
        """,
        setup="from __main__ import WORDS")
print fmt.format("'in' words",t.timeit(n),n)
print

# try
t = timeit.Timer(stmt="""
        counter = {}
        for k in LETTERS:
            try:
                counter[k]+=1
            except KeyError:
                counter[k]=1     
        """,
        setup="from __main__ import LETTERS")
print fmt.format("try letters",t.timeit(n),n)
t = timeit.Timer(stmt="""
        counter = {}
        for k in WORDS:
            try:
                counter[k]+=1
            except KeyError:
                counter[k]=1             """,
        setup="from __main__ import WORDS")
print fmt.format("try words",t.timeit(n),n)
print "\n{:,} letters and {:,} words".format(len(list(LETTERS)),len(list(WORDS)))

版画:

 defaultdict letters:   3.001 seconds for 100 loops
   defaultdict words:  0.8495 seconds for 100 loops

  setdefault letters:   4.839 seconds for 100 loops
    setdefault words:   0.946 seconds for 100 loops

     Counter letters:   7.335 seconds for 100 loops
       Counter words:   1.298 seconds for 100 loops

        'in' letters:   4.013 seconds for 100 loops
          'in' words:  0.7275 seconds for 100 loops

         try letters:   3.389 seconds for 100 loops
           try words:   1.571 seconds for 100 loops

175,176 letters and 26,630 words

個人的にはtry except、これが最速の方法の 1 つであることに驚きました。誰かわかったね...

于 2013-02-23T20:43:09.137 に答える
2

あなたが望むのはcollections.defaultdict、またはPython 2.7以降のcollections.Counterのようです。

于 2013-02-23T20:23:44.373 に答える
1

collections.Counterクラスは、(本当に) 必要なことを正確に実行します。

于 2013-02-23T20:28:00.633 に答える
1

別の方法は、try / except 句です。

try: 
    filetypecounter[filetype] += 1
except KeyError:
    filetypecounter[filetype] = 1

ファイルよりもファイルタイプが少ない場合は、この方法の方が効率filetypefiletypecounterですfiletypecounter

編集: KeyError@delnan からのコメントに応じて追加されました。

于 2013-02-23T20:25:00.050 に答える
1

必要なのはカウンターモジュールだけだと思います。

于 2013-02-23T20:25:15.323 に答える
0

私はあなたが欲しいと思うdefaultdict

from collections import defaultdict

d = defaultdict(lambda: 0)
d['foo'] += 1
# d['foo'] is now 1

別のアイデアは、次を使用することdict.setdefaultです。

d = {}
d.setdefault('foo', 0)  # won't override if 'foo' is already in d
d['foo'] += 1
于 2013-02-23T20:28:11.710 に答える