<p>下面是一个使用<a href="https://docs.python.org/3.8/library/collections.html#collections.defaultdict" rel="nofollow noreferrer">^{<cd1>}</a>的解决方案。它首先将端口分组到defaultdict列表中,然后使用<code>minmax()</code>实用程序函数输出分组的结果范围。你知道吗</p>
<pre><code>from collections import defaultdict
ports = ["1/1/1", "1/1/3", "2/1/5", "1/1/2", "2/1/6"]
def minmax(numbers):
"""Returns minumum and maximum numbers in sequence"""
return min(numbers), max(numbers)
# Group ports
d = defaultdict(list)
for port in ports:
key, number = port.rsplit("/", 1)
d[key].append(number)
print(["%s/%d-%d" % (k, *minmax(list(map(int, v)))) for k, v in d.items()])
# ['1/1/1-3', '2/1/5-6']
</code></pre>
<p><strong>注意:</strong><code>str.rsplit()</code>从右侧拆分。特别是在这种情况下,从右边开始的第一个<code>1</code>delimeter。你知道吗</p>
<p><strong>更新</p>
<p>如果要处理丢失的端口,可以尝试此函数:</p>
<pre><code>from collections import defaultdict
from operator import itemgetter
from itertools import groupby
def group_ports(ports):
result = []
# Group ports
port_groups = defaultdict(list)
for port in ports:
key, number = port.rsplit("/", 1)
port_groups[key].append(number)
# Go through each port group
for port, ranges in port_groups.items():
# Sort ranges
sorted_range = sorted(map(int, ranges))
# Iterate grouped consecutive numbers
# e.g. [1,2,3,4,6,7] -> [[1,2,3,4], [6,7]]
for _, g in groupby(enumerate(sorted_range), key=lambda x: x[0] - x[1]):
# Get only numbers in sequence
sequence = list(map(itemgetter(1), g))
# Append port strings
# Singleton sequences will be port/number, otherwise port/min-max
result.append(
"%s/%d" % (port, sequence[0])
if len(sequence) == 1
else "%s/%d-%d" % (port, sequence[0], sequence[-1])
)
return result
print(group_ports(["1/1/1", "1/1/3", "2/1/5", "1/1/2", "2/1/6"]))
print(group_ports(["1/1/1", "1/1/3", "1/1/2", "1/2/1", "1/2/3", "1/2/4"]))
</code></pre>
<p><strong>输出:</strong></p>
<pre><code>['1/1/1-3', '2/1/5-6']
['1/1/1-3', '1/2/1', '1/2/3-4']
</code></pre>