【问题标题】:Split string to dict with good performance将字符串拆分为具有良好性能的 dict
【发布时间】:2022-01-20 11:16:38
【问题描述】:

我搜索拆分长字符串的最佳方法看起来像b'a: 1\nb: 2\n ...' - 大约 50-70 个键。

字符串长度为 8-10K 字节。 所以,我每秒大约有 1K 个字符串。

最佳方法如下:

dict(x.split(b": ") for x in bytes(headers).split(b'\n'))

也许 cython 效果不错?

【问题讨论】:

标签: python string split cython


【解决方案1】:

只要输入格式正确,我们就可以用相同的分隔符 (\n) 替换 : 分隔符,并同时拆分两者,然后对键/值进行切片。

代码看起来像:

def fast_split(data):
    items = bytes(data).replace(b": ", b"\n").split(b"\n")
    return dict(zip(items[::2], items[1::2]))

在我的机器上,它大约快 3 倍-

from timeit import timeit

size = 100000
test_str = b"\n".join([b"a: 1"] * size)


def slow_split(data):
    return dict(x.split(b": ") for x in bytes(data).split(b'\n'))

def fast_split(data):
    items = bytes(data).replace(b": ", b"\n").split(b"\n")
    return dict(zip(items[::2], items[1::2]))

print(fast_split(test_str) == slow_split(test_str))

print(timeit("slow_split(test_str)", number=100, setup="from __main__ import slow_split, test_str"))
print(timeit("fast_split(test_str)", number=100, setup="from __main__ import fast_split, test_str"))
True
1.373571052972693
0.4970768200000748

【讨论】:

  • 谢谢。在我的测试数据上:慢 0:00:04.905767 和快 0:00:04.944033
  • @AlexeyPanevin 你能分享一些测试数据供我优化吗?无论是通过 pastebin,还是一个小的 python sn-p 以编程方式生成它。我想我知道为什么这目前要快得多 - 我的测试数据只有一个键(重复),因此 dict 创建本身的成本降低了
  • 测试数据是 "!adwefwersg: cdef void get_a_c_string(char** c_string_ptr, Py_ssize_t *length)" * 10000000. Prod 数据是来自 ESL freeswitch.org/confluence/display/FREESWITCH/mod_event_socket 的事件。所以,函数解析事件数据。
【解决方案2】:

将您的: 转换为\n(并删除空格)将只允许您使用一个拆分操作。字典可以通过将在 '\n' 上拆分返回的每两个值配对来创建。

sep = bytes.maketrans(b':',b'\n')

d = dict(zip(*[iter(s.translate(sep,b' ').split(b'\n'))]*2))

假设您只设置一次 sep,这大约快 2 倍(在 10,000 个不同的字典键上)。

【讨论】:

    【解决方案3】:

    也许您正在寻找这样的东西,它只会使用itertools 来节省长字符串的内存,并且:

        from itertools import pairwise
            
        def string_to_dict(str_value):
            #l is a list of indices of each '\n' inside the string ​
           ​l = []
           ​i = 0
           ​while i<len(str_value):
               ​if str_value[i] == b'\n':l.append(i)
               ​i+=1
           ​#pairwise(l) will give us a list of 2-tuple indices to get each
           # substring in the format 'key:value'
           #str_value[x[0]+1:x[1]].split(b': ') will give us (key, value) tuple
           #to dynamically create the global dict
           result_dict = dict(str_value[x[0]+1:x[1]].split(b': ') for x in pairwise(l))
           return result_dict
    

    或者更高效,以下将以计算为代价节省内存

        def string_to_dict(str_value):
            w = (i for i in range(len(str_value)) if str_value[i]==b'\n')
            result_dict = dict(str_value[x[0]+1:x[1]].split(b': ') for x in pairwise(w))
            return result_dict
    

    【讨论】:

      猜你喜欢
      • 2016-02-19
      • 1970-01-01
      • 2011-12-19
      • 2014-03-21
      • 2014-05-17
      • 2023-01-26
      • 1970-01-01
      相关资源
      最近更新 更多