我有dict
这样:
d = {'a':'b+c', 'b':'f+g', 'f':'y+u'}
我想递归地替换也是键的值中的字母,所以我最终得到:
d = {'a':'y+u+g+c', 'b':'y+u+g', 'f':'y+u'}
我尝试使用此代码:
def getval(key,d):
if d.has_key(key):
temp=re.findall('\w+',d[key])
for i in range(len(temp)):
if d.has_key(temp[i]):
getval(temp[i],d)
else:
continue
for k,v in d.iteritems():
temp=re.findall('\w+',d[k])
for i in range(len(temp)):
if d.has_key(temp[i]):
getval(temp[i],d)
但它不起作用。我该怎么做?我真正的字典要大得多,但绝对不包含任何循环。
答案 0 :(得分:1)
我实际上不确定递归是否是最合适的方法,这里是一个解决方案,在循环中进行替换,直到所有替换都不会更改当前值:
import re
def make_replacements(d):
r = d.copy()
regex = dict((k, re.compile(r'\b' + re.escape(k) + r'\b')) for k in r)
for k in r:
done = False
while not done:
done = True
for k2 in r:
n = regex[k2].sub(r[k2], r[k])
if n != r[k]:
r[k] = n
done = False
return r
print make_replacements({'a': 'b+c', 'b': 'f+g', 'f': 'y+u'})
# {'a': 'y+u+g+c', 'b': 'y+u+g', 'f': 'y+u'}
请注意,这不会检测输入中的任何循环,因此如果你给它类似{'a':'b+c','b':'c+a','c':'a+b'}
的东西,它将进入一个无限循环(尽管听起来这应该永远不会发生在你的评论中)。
答案 1 :(得分:0)
您需要将该代码放在一个函数中。然后,您的注释行应该在您想要替换的任何内容上调用该函数,将其放入字符串中,并将结果分配到dict中。
答案 2 :(得分:0)
尝试以下实施方案。
>>> def replace(d,delims,limit=5):
#Remove any whitespace characters
d=dict((k,v.translate(None,string.whitespace)) for k,v in d.iteritems())
#Escape the regex tokens
delims=re.escape(delims)
for i in range(limit): #Loop Limit, to prevent infinite Loop
changed=False
for k,v in d.iteritems():
#Its best to use regex if multiple tokens is involved
r="+".join(d.get(e,e) for e in re.split(delims,v))
if r!=v:
#Break if no change in any iteration
changed=True
d[k]=r
if not changed:
break
return d
>>> replace(d,"+")
{'a': 'y+u+g+c', 'b': 'y+u+g', 'f': 'y+u'}
答案 3 :(得分:0)
像这样的迭代方法的问题是它们的运行时对嵌套深度和dict
中项目的顺序非常敏感。此递归版本以线性时间运行,结果为dict
中的“段”总数,其中段是表达式的一部分,来自其中一个原始值。
它也不依赖于使用的符号,只要用作键的字符串不用于其他任何符号。
import re
# this function both returns and mutates
# so that each list only has to be flattened once
def flatten(lst):
new_lst = []
for i, item in enumerate(lst):
if isinstance(item, list):
new_lst.extend(flatten(item))
else:
new_lst.append(item)
lst[:] = new_lst
return lst
def flatten_symbols(d):
# split the values using the keys as delimiters
delims = re.compile('({})'.format('|'.join(d)))
d = dict((key, delims.split(value)) for key, value in d.iteritems())
# turn the value lists into recursive lists
# replacing each occurence of a key with the corresponding value
for key, value in d.iteritems():
for i, item in enumerate(value):
if item in d:
d[key][i] = d[item]
# flatten the recursive lists
return dict((key, ''.join(flatten(value))) for key, value in d.iteritems())
d={'s1':{'a':'b+c','b':'f+g', 'f': 'd+e', 'e': 'h+i'},'s2':{'a':'b+c','b':'f+g'}}
new_d = dict((key, flatten_symbols(subdict)) for key, subdict in d.iteritems())
print new_d