在递增现有值的同时向字典中添加新键

2024-10-01 13:28:53 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在处理一个CSV文件并计算第4列的唯一值。到目前为止,我已经用三种方式来编码。一个使用“if key in dictionary”,第二个陷阱捕获keyror,第三个使用“DefaultDictionary”。例如(其中x[3]是文件中的值,“a”是字典):

第一种方法:

if x[3] in a:
    a[x[3]] += 1
else:
    a[x[3]] = 1

第二种方法:

^{pr2}$

第三种方式:

from collections import defaultdict
c = defaultdict(int)
c[x[3]] += 1

我的问题是:哪种方式更有效。。。清洁工。。。更好。。。或者有更好的方法。这两种方法都有效,给出了相同的答案,但我想我应该把蜂巢思维作为一个学习案例。在

谢谢-


Tags: 文件csv方法keyin编码dictionaryif
3条回答
from collections import Counter
Counter(a)

你问哪个更有效。假设您谈论的是执行速度:如果您的数据很小,则无所谓。如果它是大的和典型的,那么“已经存在”的情况将比“不在dict中”的情况更频繁地发生。这个观察结果解释了一些结果。在

下面是一些代码,可以与timeit模块一起使用,以探索速度而不增加文件读取开销。我已经冒昧地添加了一个第五个方法,它不是没有竞争力的,至少从1.5.2[测试]以后的任何Python上都可以运行。在

from collections import defaultdict, Counter

def tally0(iterable):
    # DOESN'T WORK -- common base case for timing
    d = {}
    for item in iterable:
        d[item] = 1
    return d

def tally1(iterable):
    d = {}
    for item in iterable:
        if item in d:
            d[item] += 1
        else:
            d[item] = 1
    return d

def tally2(iterable):
    d = {}
    for item in iterable:
        try:
            d[item] += 1
        except KeyError:
            d[item] = 1
    return d

def tally3(iterable):
    d = defaultdict(int)
    for item in iterable:
        d[item] += 1

def tally4(iterable):
    d = Counter()
    for item in iterable:
        d[item] += 1

def tally5(iterable):
    d = {}
    dg = d.get
    for item in iterable:
        d[item] = dg(item, 0) + 1
    return d

典型运行(在Windows XP“命令提示符”窗口中):

^{pr2}$

以下是结果(每循环毫秒数):

0 base case   13.6
1 if k in d   29.5
2 try/except  26.1
3 defaultdict 23.4
4 Counter     79.4
5 d.get(k, 0) 29.2

另一次计时试验:

prompt>\python27\python -mtimeit -s"from collections import defaultdict;d=defaultdict(int)" "d[1]+=1"
1000000 loops, best of 3: 0.309 usec per loop

prompt>\python27\python -mtimeit -s"from collections import Counter;d=Counter()" "d[1]+=1"
1000000 loops, best of 3: 1.02 usec per loop

Counter的速度可能是因为它部分是用Python代码实现的,而defaultdict完全是用C实现的(至少在2.7中)。在

请注意,Counter()不仅仅是defaultdict(int)的“语法糖”——它实现了一个完整的bag又名multiset对象——有关详细信息,请参阅文档;如果您需要一些奇特的后处理,它们可能会帮助您避免重新发明轮子。如果您只想数数,请使用defaultdict。在

更新在回答@Steven Rumbalski的问题时:“我很好奇,如果将iterable移到Counter构造函数中:d=Counter(iterable)?(我有Python2.6,无法测试。)“”“

tally6:只执行d = Count(iterable); return d,需要60.0毫秒

你可以看看源头(收藏.py在SVN存储库中。。。以下是当iterable不是映射实例时,Python27\Lib\collections.py的操作:

            self_get = self.get
            for elem in iterable:
                self[elem] = self_get(elem, 0) + 1

以前在任何地方见过那个密码吗?在python1.5.2:-O中调用可运行的代码有很多

使用collections.CounterCounterdefaultdict(int)的语法甜点,但它的酷之处在于它在构造函数中接受一个iterable,从而节省了额外的一步(我假设上面的所有示例都包装在for循环中)

from collections import Counter
count = Counter(x[3] for x in my_csv_reader)

在引入collections.Counter之前,collections.defaultdict是该任务最惯用的用法,因此对于用户<;2.7,请使用defaultdict。在

^{pr2}$

相关问题 更多 >