Set value in dictionary if value not there?
本问题已经有最佳答案,请猛点这里访问。
我用字典来存储一堆计数器,每个计数器都在计算文件类型(.wav,.mp3等)的出现次数。
1 | filetypecounter = {} |
当我遇到某个文件类型时,我希望能够以Python式的方式增加计数器。所以我想…
1 | filetypecounter[filetype] +=1 |
但是,如果文件类型不在字典中,我想将其实例化为1。所以我的逻辑是,如果有filetype计数器,在计数器值上加1,否则设置为1。
1 2 3 4 | if filetype not in filetypecounter: filetypecounter[filetype] = 1 else: filetypecounter[filetype] +=1 |
有没有更像Python的方法?
1 2 3 4 | from collections import defaultdict filetypecounter = defaultdict(int) filetypecounter[filetype] += 1 |
或
1 2 3 4 | from collections import Counter filetypecounter = Counter() filetypecounter.update([filetype]) |
有关信息,如果您必须使用
1 2 | filetypecounter = {} filetypecounter[filetype] = filetypecounter.get(filetype, 0) + 1 |
实际上,这和其他建议只是同一主题的变体。我用一下柜台。
在这组答案中,很好地使用
一个古老的方法是:
1 2 3 4 5 6 | >>> d={} >>> for ext in ('.mp3','.mp3','.m4a','.mp3','.wav','.m4a'): ... d[ext]=d.setdefault(ext,0)+1 ... >>> d {'.mp3': 3, '.wav': 1, '.m4a': 2} |
这也不是最快的,但比
这些方法都有基准,无论是defaultdict、try/except还是您的原始方法都是最快的。
我在这里复制(并扩展)了基准:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | import urllib2 import timeit response = urllib2.urlopen('http://pastebin.com/raw.php?i=7p3uycAz') hamlet = response.read().replace(' ',' ') LETTERS = [w for w in hamlet] WORDS = hamlet.split(' ') fmt='{:>20}: {:7.4} seconds for {} loops' n=100 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) # 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) # 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) # 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) # 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" {:,} letters and {:,} words".format(len(list(LETTERS)),len(list(WORDS))) |
印刷品:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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 |
就我个人而言,我很惊讶于
您想要的是collections.defaultdict或collections.counter for python 2.7及更高版本。
collections.counter类完全满足您的需要。
我想你只需要计数器模块。
另一种方法是try/except子句:
1 2 3 4 | try: filetypecounter[filetype] += 1 except KeyError: filetypecounter[filetype] = 1 |
如果文件类型比文件少,则此方法更有效,因为您不必不必要地检查
编辑:根据@delnan的评论增加了EDOCX1[3]。
我想你要的是
1 2 3 4 5 | from collections import defaultdict d = defaultdict(lambda: 0) d['foo'] += 1 # d['foo'] is now 1 |
另一个想法是使用
1 2 3 | d = {} d.setdefault('foo', 0) # won't override if 'foo' is already in d d['foo'] += 1 |