性能问题:查找 python 字典的子值(如果它与另一个值匹配)

Performance Issue: Lookup sub-value of python dictionary if it is matching another value

我有一个 python 字典如下。同样,字典可能有 2 个逗号分隔值 'Var'(即 Dep1,Dep2),然后是它们各自的子值(ABC1||A1B1||B1C1,ABC2||A2B2||B2C2)。

我正在尝试提取值 A1B1(或 A1B1 和 B1C1,如果有两个 Var)与 mainValue 'ABC1' 的匹配和 SubVal 'ABC1' 的前缀。

ld = { 'id' : 0
      'Var': 'Dep1'
      'SubVal': 'ABC1||A1B1,ABC2||A2B2,ABC3||A3B3',
      'MainValue': 'ABC1'}

到目前为止,我尝试将 Subval 拆分为列表(以逗号分隔),然后将每对(|| 分隔)转换为另一个字典,然后查找匹配项。 谁能在性能方面提出更好的方法来做到这一点?

设:

>>> ld = { 'id' : 0, 'Var': 'Dep1', 'SubVal': 'ABC1||A1B1,ABC2||A2B2,ABC3||A3B3', 'MainValue': 'ABC1'}

你的split + dict解决方案大致是(注意maxsplit参数来处理ABC1||A1B1||B1C1个案例):

>>> def parse(d):
...     sub_val = dict(t.split('||', maxsplit=1) for t in ld['SubVal'].split(","))
...     return sub_val[d['MainValue']]

>>> parse(ld)
'A1B1'

基准给出:

>>> import timeit
>>> timeit.timeit(lambda: parse(ld))
1.002971081999931

您为一次性查找构建字典:这有点矫枉过正。您可以直接查找 MainValue:

>>> def parse_iter(d):
...     mv = d['MainValue']
...     g = (t.split('||', maxsplit=1) for t in d['SubVal'].split(","))
...     return next(v for k, v in g if k == mv)

>>> parse_iter(ld)
'A1B1'

快一点:

>>> timeit.timeit(lambda: parse_iter(ld))
0.8656512869993094

一种更快的方法是在 ld[SubVal] 字符串中查找 MainValue 并提取正确的 SubVal。 (我假设 MainValue 不能是 SubValSubVal 的子串)。

使用正则表达式:

>>> import re
>>> def parse_re(d):
...     pattern = d['MainValue']+"\|\|([^,]+)"
...     return re.search(pattern, d['SubVal']).group(1)

>>> parse_re(ld)
'A1B1'

这比示例中的第一个版本快了大约 25%:

>>> timeit.timeit(lambda: parse_re(ld))
0.7367669239997667

但为什么不手动执行搜索呢?

>>> def parse_search(d):
...     s = d['SubVal']
...     mv = d['MainValue']
...     i = s.index(mv) + len(mv) + 2 # after the ||
...     j = s.index(",", i)
...     return s[i:j]

>>> parse_search(ld)
'A1B1'

这个版本比第一个版本快 60% 左右(在给定的例子中):

>>> timeit.timeit(lambda: parse_search(ld))
0.3840863969999191

(如果MainValue可以是SubVal,你可以检查MainValueSubVal前面是否有逗号以MainValue开头.)