性能问题:查找 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
不能是 SubVal
或 SubVal
的子串)。
使用正则表达式:
>>> 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
,你可以检查MainValue
或SubVal
前面是否有逗号以MainValue
开头.)
我有一个 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
不能是 SubVal
或 SubVal
的子串)。
使用正则表达式:
>>> 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
,你可以检查MainValue
或SubVal
前面是否有逗号以MainValue
开头.)