将字典键拆分为字符串类型元组并将另一个字符串附加到元组中的最后项目的最快方法是什么?

alv*_*vas 7 python string dictionary tuples

给定字符串键和整数值的字典,最快的方法是什么

  1. 将每个键拆分为字符串型键元组
  2. 然后将一个特殊的子字符串追加</w>到元组中的最后一项

鉴于:

counter = {'The': 6149,
     'Project': 205,
     'Gutenberg': 78,
     'EBook': 5,
     'of': 39169,
     'Adventures': 2,
     'Sherlock': 95,
     'Holmes': 198,
     'by': 6384,
     'Sir': 30,
     'Arthur': 18,
     'Conan': 3,
     'Doyle': 2,}
Run Code Online (Sandbox Code Playgroud)

目标是实现:

counter = {('T', 'h', 'e</w>'): 6149,
 ('P', 'r', 'o', 'j', 'e', 'c', 't</w>'): 205,
 ('G', 'u', 't', 'e', 'n', 'b', 'e', 'r', 'g</w>'): 78,
 ('E', 'B', 'o', 'o', 'k</w>'): 5,
 ('o', 'f</w>'): 39169,
 ('A', 'd', 'v', 'e', 'n', 't', 'u', 'r', 'e', 's</w>'): 2,
 ('S', 'h', 'e', 'r', 'l', 'o', 'c', 'k</w>'): 95,
 ('H', 'o', 'l', 'm', 'e', 's</w>'): 198,
 ('b', 'y</w>'): 6384,
 ('S', 'i', 'r</w>'): 30,
 ('A', 'r', 't', 'h', 'u', 'r</w>'): 18,
 ('C', 'o', 'n', 'a', 'n</w>'): 3,
 ('D', 'o', 'y', 'l', 'e</w>'): 2,}
Run Code Online (Sandbox Code Playgroud)

一种方法是

  • 迭代通过柜台和
  • 将除最后一个字符之外的所有字符转换为元组
  • 添加到元组并创建外部元组
  • 并将元组键分配给计数

我试过了

{(tuple(k[:-1])+(k[-1]+'</w>',) ,v) for k,v in counter.items()}
Run Code Online (Sandbox Code Playgroud)

更详细的形式:

new_counter = {}
for k, v in counter.items():
    left = tuple(k[:-1])
    right = tuple(k[-1]+'w',)
    new_k = (left + right,)
    new_counter[new_k] = v
Run Code Online (Sandbox Code Playgroud)

有一个更好的方法吗?

关于添加元组并将其转换为外部元组.为什么允许这样做?元组应该是不可变的吗?

Soh*_*oqi 5

我建议您稍微修改一下您的解决方案.您可以使用元组解包来代替使用元组构造函数:

>>> {(*a[:-1],f'a[-1]</w>',):b for a,b in counter.items()}
Run Code Online (Sandbox Code Playgroud)

使用元组解包的好处是,与tuple构造函数相比,您将获得更好的性能.我将通过使用更多地阐明这一点timeit.我将使用随机生成的dict.dict将使用小写字母表中的每个键具有2个随机选择的字符,每个值将是0-100范围内的整数.对于所有这些基准测试,我使用的是Python 3.7.0

在dict中有100个元素的基准

$ python -m timeit -s "import random" -s "import string" -s "counter = {''.join(random.sample(string.ascii_lowercase,2)): random.randint(0,100) for _ in range(100)}" "{(*a[:-1],f'a[-1]</w>',):b for a,b in counter.items()}
$ 10000 loops, best of 5: 36.6 usec per loop

$ python -m timeit -s "import random" -s "import string" -s "counter = {''.join(random.sample(string.ascii_lowercase,2)): random.randint(0,100) for _ in range(100)}" "{tuple(key[:-1])+(key[-1]+'</w>',):value for key,value in counter.items()}"
$ 5000 loops, best of 5: 59.7 usec per loop
Run Code Online (Sandbox Code Playgroud)

在dict中有1000个元素的基准

$ python -m timeit -s "import random" -s "import string" -s "counter = {''.join(random.sample(string.ascii_lowercase,2)): random.randint(0,100) for _ in range(1000)}" "{(*a[:-1],f'a[-1]</w>',):b for a,b in counter.items()}"
$ 1000 loops, best of 5: 192 usec per loop

$ python -m timeit -s "import random" -s "import string" -s "counter = {''.join(random.sample(string.ascii_lowercase,2)): random.randint(0,100) for _ in range(1000)}" "{tuple(key[:-1])+(key[-1]+'</w>',):value for key,value in counter.items()}"
$ 1000 loops, best of 5: 321 usec per loop
Run Code Online (Sandbox Code Playgroud)

基准与dict张贴有问题

$ python -m timeit -s "import random" -s "import string" -s "counter = counter = {'The': 6149, 'Project': 205, 'Gutenberg': 78, 'EBook': 5, 'of': 39169, 'Adventures': 2, 'Sherlock': 95, 'Holmes': 198, 'by': 6384, 'Sir': 30, 'Arthur': 18, 'Conan': 3,'Doyle': 2}" "{(*a[:-1],f'a[-1]</w>',):b for a,b in counter.items()}"
$ 50000 loops, best of 5: 7.28 usec per loop

$ python -m timeit -s "import random" -s "import string" -s "counter = counter = {'The': 6149, 'Project': 205, 'Gutenberg': 78, 'EBook': 5, 'of': 39169, 'Adventures': 2, 'Sherlock': 95, 'Holmes': 198, 'by': 6384, 'Sir': 30, 'Arthur': 18, 'Conan': 3,'Doyle': 2}" "{tuple(key[:-1])+(key[-1]+'</w>',):value for key,value in counter.items()}"
$ 20000 loops, best of 5: 11 usec per loop
Run Code Online (Sandbox Code Playgroud)