问题描述
不确定标题是否具有描述性,但这是我的问题。给定路径和可选参数,例如:
/client/get
/admin/client/get
/admin/client/get/2
我如何生成一个表达该URL每种可能版本的模板。对于该示例,它将类似于:
/{admin}/client/get/{id}
我的主要问题是保持路径顺序。虽然我可以生成包含所有参数的路径,但似乎无法以正确的顺序进行操作。得到的模板如下:
/client/get/{id}/{admin}
我在python列表中将所有路径都作为字符串,没有特定的顺序,例如:
/client/get
/admin/client/get/<int:id>
/admin/client/get
解决方法
可能不是最优化的方法,但是我最终将路径段上的权重关联在一起。从最短的url开始,我检测到新的部分和被删除的部分,然后假定它们是参数。在最短路径上,我使用10的增量来保留我认为是合理的空间。 diff方法仅返回两个列表之间的差。我还在元组中使用了第三个元素,指示该参数是否可选,允许我添加一个“?”在模板中。该代码不是很干净,但是效果很好:
shortest_string = reduce(lambda a,b: a if len(a) <= len(b) else b,paths)
paths.remove(shortest_string)
shortest = [e for e in shortest_string.split('/') if len(e) > 0]
weighted = [((i + 1) * 10,v,False) for i,v in enumerate(shortest)]
for p in paths:
psplit = [e for e in p.split('/') if len(e) > 0]
new_elements = diff(psplit,shortest)
removed_elements = diff(shortest,psplit)
for w in weighted:
if w[1] in removed_elements:
w[2] = True
if w[1] in psplit:
i = psplit.index(w[1])
psplit[i] = w
for i,ps in enumerate(psplit):
if i < len(psplit) - 2 and isinstance(psplit[i + 1],tuple) and not isinstance(ps,tuple):
psplit[i] = (psplit[i + 1][0] - 1,ps,ps in new_elements)
weighted.append(psplit[i])
elif not isinstance(ps,tuple):
psplit[i] = (psplit[i - 1][0] + 1,ps in new_elements)
weighted.append(psplit[i])
template = '/'.join(['{' + (e[1][1:-1].split(':')[1] if e[1].startswith('<') else e[1]) + ('?' if e[2] else '') + '}'
if e[2] or e[1].startswith('<') else e[1] for e in sorted(weighted,key=lambda x: x[0])[1:]])
,
如果所有路径都在python列表中,则从选择最短路径开始,因为最短路径是缺少所有可选参数的路径(在示例中为“ / client / get”)
然后,您使用诸如RegExp之类的模式匹配在列表的开头或末尾浏览可选参数添加项
import re
# holds smallest possible url
shortest = '/client/get'
# holds the url template you want
template = '/client/get'
# iterates through URLs
for poss_url in url_list:
# Checks beginning of URL
match = re.search('w+' + shortest,poss_url)
if match is not None:
string = match.group()
string = string[1:]
string = string[:-len(shortest)]
template = '/{' + string + '}' + template
# Checks end of URL
match = re.search(shortest + 'w+',poss_url)
if match is not None:
string = match.group()
string = string[1:]
string = string[:-len(shortest)]
template = template + '{' + string + '}'