RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1471805
Accepted
Qwertiy
Qwertiy
Asked:2022-11-28 09:21:27 +0000 UTC2022-11-28 09:21:27 +0000 UTC 2022-11-28 09:21:27 +0000 UTC

在Counter中收集加权值

  • 772

有一个 pairs 列表,(ключ,значение)键可以重复。我想以汇总Counter相同键的值的方式收集所有内容。

我可以这样做:tio.run

from collections import Counter

a = [("A",3), ("B",10), ("A",8), ("C",1)]

c = Counter()
for k,v in a: c[k] += v

print(c) # Counter({'A': 11, 'B': 10, 'C': 1})

有没有更漂亮的方法来获得相同的?

python
  • 4 4 个回答
  • 40 Views

4 个回答

  • Voted
  1. Виктор
    2022-11-28T10:19:29Z2022-11-28T10:19:29Z

    “有没有更漂亮的方法来得到同样的东西?” - 每个人都有自己的美丽:)

    相同,没有额外的模块:

    a = [("A",3), ("B",10), ("A",8), ("C",1)]
    
    c = {}
    for k,v in a:
        c[k] = v if k not in c else c[k] + v
    
    print(c)
    

    输出:{'A': 11, 'B': 10, 'C': 1}

    方法有不同的目标:美丽或速度

    import timeit
    from collections import Counter
    
    def proc():
        a = [("A",3), ("B",10), ("A",8), ("C",1)]
        c = Counter()
        for k,v in a: c[k] += v
    
    def proc2():
        a = [("A",3), ("B",10), ("A",8), ("C",1)]
        c = {}
        for k,v in a:
            c[k] = v if k not in c else c[k] + v
    
    print(timeit.timeit(proc2, number=100000))
    print(timeit.timeit(proc, number=100000))
    

    结果:

    100000 прогонов
    proc2: 0.0937448000004224
    proc:  0.3667998000000807
    
    1000000 прогонов
    proc2: 0.9124658000000636                                                                                  
    proc:  3.624726500000179
    

    结果很明显

    • 4
  2. extrn
    2022-11-28T12:23:11Z2022-11-28T12:23:11Z

    您的选择可能在速度上没有可比性。

    需要c[k] += v在Counter(的直接后代dict)中执行的操作不会被覆盖,并且与在中一样快,dict因为它们是本机实现的。但是所有特定于操作的操作Counter(除了使用 iterable 进行初始化/更新)都是用 python 编写的,并且预计会慢得多。

    但这里有几个选项可以增强美感

    c = sum((Counter({k: v}) for k, v in a), start=Counter()) # В худшем случае O(n*n)
    
    c = Counter(k for k, v in a for _ in range(v)) # В худшем случае O(n*max(v))
    

    最好的情况是,这两个选项都比你的慢,最坏的情况是 - 只是慢了很多。

    • 2
  3. Best Answer
    CrazyElf
    2022-11-28T15:33:39Z2022-11-28T15:33:39Z

    事实上,事实证明Counter你根本不用 main 功能,那还不如拿来用defaultdict,这样会更快(但仍然比计数器字典“手动”检查元素是否存在要慢):

    from collections import defaultdict
    
    a = [("A",3), ("B",10), ("A",8), ("C",1)]
    
    c = defaultdict(int)
    for k, v in a: 
        c[k] += v
    
    print(c) # defaultdict(<class 'int'>, {'A': 11, 'B': 10, 'C': 1})
    
    • 2
  4. Qwertiy
    2022-11-29T00:47:43Z2022-11-29T00:47:43Z

    使用线性渐近法测量建议的答案:计数器是最慢的 - 比其他方法差大约 2 倍,并且使用字典,所有方法都给出误差范围内的结果。tio.run

    from collections import Counter, defaultdict
    from random import randint
    from timeit import timeit
    
    def viaCounter():
      c = Counter()
      for k,v in a: c[k] += v
      return c
    
    def viaDictCheck():
      c = {}
      for k,v in a: c[k] = v if k not in c else c[k] + v
      return c
    
    def viaDictGet():
      c = {}
      for k,v in a: c[k] = c.get(k, 0) + v
      return c
    
    def viaDefaultDict():
      c = defaultdict(int)
      for k,v in a: c[k] += v
      return c
    
    ways = [viaCounter, viaDictCheck, viaDictGet, viaDefaultDict]
    
    a = [("A",3), ("B",10), ("A",8), ("C",1)]
    for f in ways: print(f"{f.__name__:16}", f())
    
    for n in [10, 100, 1000, 10000]:
      print()
      print("===", n, "===")
      a = [(randint(0,1024), randint(0,1024)) for _ in range(n)]
      for f in ways: print(f"{f.__name__:16}", timeit(f, number=1000))
    

    结果:

    viaCounter       Counter({'A': 11, 'B': 10, 'C': 1})
    viaDictCheck     {'A': 11, 'B': 10, 'C': 1}
    viaDictGet       {'A': 11, 'B': 10, 'C': 1}
    viaDefaultDict   defaultdict(<class 'int'>, {'A': 11, 'B': 10, 'C': 1})
    
    === 10 ===
    viaCounter       0.005354834022000432
    viaDictCheck     0.000977317977230996
    viaDictGet       0.001639115042053163
    viaDefaultDict   0.00273122702492401
    
    === 100 ===
    viaCounter       0.041808484005741775
    viaDictCheck     0.011960842995904386
    viaDictGet       0.01808635302586481
    viaDefaultDict   0.02747832500608638
    
    === 1000 ===
    viaCounter       0.40349273895844817
    viaDictCheck     0.16457551100756973
    viaDictGet       0.239735366019886
    viaDefaultDict   0.24876780400518328
    
    === 10000 ===
    viaCounter       3.3196506010135636
    viaDictCheck     1.8371806619688869
    viaDictGet       1.956588956003543
    viaDefaultDict   1.7752377989818342
    
    • 1

相关问题

  • 是否可以以某种方式自定义 QTabWidget?

  • telebot.anihelper.ApiException 错误

  • Python。检查一个数字是否是 3 的幂。输出 无

  • 解析多个响应

  • 交换两个数组的元素,以便它们的新内容也反转

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5