Sep-09-2019, 11:07 AM
Here a different approach. Before you must do a transformation, that all ports are in a list.
unsorted_ports = [item['port'] for item in data]
def find_port_ranges(ports): # the set returns only unique elements # then the set is sorted in reversed order # the resulting object is a sorted list ports = sorted(set(ports), reverse=True) # pop the last element from list, which is the smallest start = last = ports.pop() # start indicates the start range # last is always the value from previous iteration # repeat until the list ports is empty while ports: # pop the last element from list value = ports.pop() if value - 1 != last: yield (start, last) start = last = value else: # last value is current value - 1 last = value # yield the last elements yield (start, value)Test:
Output:>>> example_ports = [1,2,4,3,20,10,11,13,12,21,23,28,22,25,26,29,100,101,103]
>>> list(find_port_ranges(example_ports))
[(1, 4), (10, 13), (20, 23), (25, 26), (28, 29), (100, 101), (103, 103)]
A second function can do the formatting:def format_port_ranges(ports): ranges = [] for start, end in find_port_ranges(ports): if start != end: ranges.append(f'{start}-{end}') else: ranges.append(str(start)) return 'Ports: ' + ', '.join(ranges) # split ranges by comma
Output:>>> format_port_ranges([1,2,3,4,10,20,11,12,13,21,22,23,22,25,26,29])
'Ports: 1-4, 10-13, 20-23, 25-26, 29'
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
All humans together. We don't need politicians!