РЕДАКТИРОВАТЬ Эта запись теперь состоит из трех частей:
1) Немного информации о словарях, которая понадобится вам для понимания всего остального.
2) Анализ вашего кода, и как вы можете это исправить, не используя какие-либо другие функции Python.
3) Что бы я посчитал лучшим решением проблемы, подробно.
1) Словари
Словари Python не упорядочены. Если у меня есть словарь, как это:
dictionary = {"one": 1, "two": 2}
И я перебираю словарь dictionary.items (), я мог получить «один»: 1 первым, или я мог получить «два»: 2 первым. Я не знаю.
Каждый словарь Python неявно имеет два списка, связанных с ним: список его ключей и список его значений. Вы можете получить их перечислить это:
print(list(dictionary.keys()))
print(list(dictionary.values()))
Эти списки имеют порядок. Таким образом, они могут быть отсортированы. Конечно, это не изменит исходный словарь.
Ваш код
Что вы поняли, так это то, что в вашем случае вы хотите сортировать только по первому IP-адресу в ключах ваших словарей. Поэтому стратегия, которую вы приняли, выглядит примерно так:
1) Создайте новый словарь, где ключами являются только эта первая часть.
2) Получить этот список ключей из словаря.
3) Сортировать этот список ключей.
4) Запросить исходный словарь для значений.
Этот подход, как вы заметили, потерпит неудачу на шаге 1. Потому что, как только вы создадите новый словарь с усеченными ключами, вы потеряете способность различать некоторые ключи, которые в конце были различны. Каждый ключ словаря должен быть уникальным.
Лучшая стратегия была бы:
1) Создайте функцию, которая может представлять ваши «полные» IP-адреса в качестве объекта ip_address.
2) Сортировать список ключей словаря (оригинальный словарь, не создавайте новый).
3) Запросить словарь по порядку.
Давайте посмотрим, как мы могли бы изменить ваш код для реализации шага 1.
def represent(full_ip):
if '-' in full_ip:
# Stylistic note, never use o or l as variable names.
# They look just like 0 and 1.
first_part = full_ip.split('-')[0]
return ipaddress.ip_address(first_part.strip())
Теперь, когда у нас есть способ представления полных IP-адресов, мы можем отсортировать их в соответствии с этой сокращенной версией, без необходимости вообще менять ключи. Все, что нам нужно сделать, это сообщить отсортированному методу Python, как мы хотим, чтобы ключ был представлен, используя параметр ключа (NB, этот параметр ключа не имеет ничего общего с ключом в словаре. Просто они оба были названы ключом.):
# Another stylistic note, always use .keys() when looping over dictionary keys. Explicit is better than implicit.
sips = sorted(sresults.keys(), key=represent)
И если эта библиотека ipaddress работает, проблем здесь быть не должно. Оставшуюся часть кода вы можете использовать как есть.
Часть 3 Лучшее решение
Когда бы вы ни занимались сортировкой чего-либо, всегда легче думать о гораздо более простой проблеме: учитывая два элемента, как бы я их сравнил? Python дает нам способ сделать это. Нам нужно реализовать два метода модели данных, которые называются
__le__
и
__eq__
Давайте попробуем сделать это:
class IPAddress:
def __init__(self, ip_address):
self.ip_address = ip_address # This will be the full IP address
def __le__(self, other):
""" Is this object less than or equal to the other one?"""
# First, let's find the first parts of the ip addresses
this_first_ip = self.ip_address.split("-")[0]
other_first_ip = other.ip_address.split("-")[0]
# Now let's put them into the external library
this_object = ipaddress.ip_address(this_first_ip)
other_object = ipaddress.ip_adress(other_first_ip)
return this_object <= other_object
def __eq__(self, other):
"""Are the two objects equal?"""
return self.ip_address == other.ip_adress
Круто, у нас есть класс. Теперь методы модели данных будут автоматически вызываться каждый раз, когда я использую «<» или «<=» или «==». Давайте проверим, что это работает: </p>
test_ip_1 = IPAddress("10.102.152.64-10.102.152.95")
test_ip_2 = IPAddress("10.102.158.0-10.102.158.255")
print(test_ip_1 <= test_ip_2)
Теперь, прелесть этих методов модели данных в том, что Питоны "сортируют" и "сортируют" также будут использовать их:
dictionary_keys = sresult.keys()
dictionary_key_objects = [IPAddress(key) for key in dictionary_keys]
sorted_dictionary_key_objects = sorted(dictionary_key_objects)
# According to you latest comment, the line below is what you are missing
sorted_dictionary_keys = [object.ip_address for object in sorted_dictionary_key_objects]
А теперь вы можете сделать:
for key in sorted_dictionary_keys:
print(key)
print(sresults[key])
Модель данных Python является почти определяющей особенностью Python. Я бы порекомендовал прочитать об этом.