gpt4 book ai didi

python - 删除主机名的公共(public)元素(缩短主机名)- DRY

转载 作者:太空狗 更新时间:2023-10-30 02:32:04 25 4
gpt4 key购买 nike

解释:

我编写了以下函数来缩短生产中使用的机器的主机名。此处更改了名称,但保留了相同的结构和格式。下面的代码很笨重,我想将代码设为 DRY (Don't Repeat Yourself) .可读性也很重要,因为这些代码可能需要由不止我自己维护或理解。

代码:

def shorten_hostnames(machines):
# split items
d = {k: v.split('.') for k, v in machines.items()}
# trim end
while all(d.values()):
if not len(set([v[-1] for v in d.values()])) == 1:
break
if not all(len(v) > 1 for v in d.values()):
break
d = {k: v[:-1] for k, v in d.items()}
# trim start
while all(d.values()):
if not len(set([v[0] for v in d.values()])) == 1:
break
if not all(len(v) > 1 for v in d.values()):
break
d = {k: v[1:] for k, v in d.items()}
# join items
d = {k: '.'.join(v) for k, v in d.items()}
# return shortened hostnames
return d

示例输入:

machines = {'a.ace.site.info': 'a.ace.site.info',
'b.ace.site.info': 'b.ace.site.info',
'a.bob.site.info': 'a.bob.site.info',
'b.bob.site.info': 'b.bob.site.info',}

输出:

>>> for k, v in shorten_hostnames(machines).items():
print k, '-->', v

b.ace.site.info --> b.ace
a.ace.site.info --> a.ace
b.bob.site.info --> b.bob
a.bob.site.info --> a.bob

我在哪里以及为什么需要的帮助:

我试图嵌入一个函数,该函数会根据提供的参数从任一端进行修剪,但我无法弄清楚如何修改切片符号以从列表的开头或结尾进行修剪。我确信我忽略了一个简单的解决方案,无论是使用切片符号还是其他东西。

陷阱:

这里有几件事需要提及,即所谓的“疑难杂症”。如果只有一个主机名被传递到函数中,(例如 machines = {'a.ace.site.info': 'a.ace.site.info'})它应该只返回第一部分(在示例中 a)。另外 - 最终答案中不应有重复结果。此外 - 主机名可以彼此具有不同的长度(不同数量的段)

事后思考:

一旦找到合适的解决方案,我将编辑问题标题和标签,以更好地反射(reflect)如何将其应用于网站的 future 访问者。例如,如果切片表示法是解决方案(并且可以动态应用),我可能会修改问题以反射(reflect)动态切片表示法是问题的主题。

更多示例输入和预期输出:

# In
machines = {'ace.a.site.info': 'ace.a.site.info',
'ace.b.site.info': 'ace.b.site.info',}
# Out
ace.b.site.info --> b
ace.a.site.info --> a

# In
machines = {'a.ace.site.info': 'a.ace.site.info',}
# Out
a.ace.site.info --> a

# In
machines = {'ace.a.site.info': 'ace.a.site.info',
'ace.b.site.com': 'ace.b.site.com',}
# Out
ace.b.site.com --> b.site.com
ace.a.site.info --> a.site.info

最佳答案

至少,将值和键拆分成单独的列表,然后在重构字典之前只处理值,并使用一个短循环来选择开始和结束修剪的索引:

def shorten_hostnames(machines):
keys, values = zip(*machines.items())
values = [v.split('.') for v in values]
for i, s in ((-1, slice(-1)), (0, slice(1, None))):
while all(values):
if not len(set(v[i] for v in values)) == 1:
break
if any(len(v) <= 1 for v in values):
break
values = [v[s] for v in values]
return {k: '.'.join(v) for k, v in zip(keys, values)}

我会使用实用函数从一系列序列中删除公共(public)前缀,然后传入反向序列以删除尾随部分:

from itertools import dropwhile, izip_longest

def remove_common_prefix(*parts):
# always leaves a last common element in place
zipped = izip_longest(*(p[:-1] for p in parts), fillvalue=None)
stripped = dropwhile(lambda v: len(set(v)) == 1, zipped)
res = [filter(None, part) + (old[-1],) for part, old in zip(zip(*stripped), parts)]
# filtered everything away? Then return just the last parts
return res or [p[-1:] for p in parts]

def shorten_hostnames(machines):
# edge-case; faster to just return the first part
if len(machines) == 1:
return {k: v.split('.', 1)[0] for k, v in machines.items()}
keys, values = zip(*machines.items()) # for easier processing and re-assembling
parts = remove_common_prefix(*(v.split('.')[::-1] for v in values))
parts = remove_common_prefix(*(part[::-1] for part in parts))
return {k: '.'.join(v) for k, v in zip(keys, parts)}

这会处理您的输入和不均匀长度的名称:

>>> shorten_hostnames(machines)
{'b.ace.site.info': 'b.ace', 'a.ace.site.info': 'a.ace', 'b.bob.site.info': 'b.bob', 'a.bob.site.info': 'a.bob'}
>>> shorten_hostnames({'foo': 'a.ace.site', 'bar': 'a.ace.site.info'})
{'foo': 'site', 'bar': 'site.info'}
>>> shorten_hostnames({'ace.a.site.info': 'ace.a.site.info', 'ace.b.site.info': 'ace.b.site.info'})
{'ace.b.site.info': 'b', 'ace.a.site.info': 'a'}
>>> shorten_hostnames({'ace.a.site.info': 'ace.a.site.info'})
{'ace.a.site.info': 'ace'}

关于python - 删除主机名的公共(public)元素(缩短主机名)- DRY,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20240210/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com