Python:对作为字典键的ip范围进行排序
我有一个字典,它将IP地址范围作为键,用于在上一步中消除重复,并将某些对象作为值。这里有一个例子 词典的一部分sresult: 有上万行,我想按密钥中的IP地址正确排序 我尝试根据范围分隔符拆分密钥-以获得单个IP地址,该地址可以按如下方式排序:Python:对作为字典键的ip范围进行排序,python,sorting,dictionary,ip-address,Python,Sorting,Dictionary,Ip Address,我有一个字典,它将IP地址范围作为键,用于在上一步中消除重复,并将某些对象作为值。这里有一个例子 词典的一部分sresult: 有上万行,我想按密钥中的IP地址正确排序 我尝试根据范围分隔符拆分密钥-以获得单个IP地址,该地址可以按如下方式排序: ips={} for key in sresult: if '-' in key: l = key.split('-')[0] ips[l] = key else: ips[1] = ke
ips={}
for key in sresult:
if '-' in key:
l = key.split('-')[0]
ips[l] = key
else:
ips[1] = key
然后使用另一篇文章中的代码,按IP地址排序,然后在原始字典中查找值:
sips = sorted(ipaddress.ip_address(line.strip()) for line in ips)
for x in sips:
print("SRC: "+ips[str(x)], "OBJECT: "+" :".join(list(set(sresult[ips[str(x)]]))), sep=",")
我遇到的问题是,当我拆分原始范围并将排序后的第一个IP作为新键添加到另一个字典中时,我再次消除了重复,丢失了数据行—示例中的第2行和第3行
line 1 10.102.152.64 -10.102.152.95
line 2 10.102.158.0 -10.102.158.255
line 3 10.102.158.0 -10.102.158.31
line 4 10.102.159.0 -10.102.255.25
变成
line 1 10.102.152.64 -10.102.152.95
line 3 10.102.158.0 -10.102.158.31
line 4 10.102.159.0 -10.102.255.25
因此,在使用IP地址排序键重建原始字典时,我丢失了数据
有人能帮忙吗?编辑这篇文章现在由三部分组成:
1为理解其余部分,您需要了解一些有关词典的信息。
2对代码的分析,以及如何在不使用任何其他Python功能的情况下修复代码。
3,我将详细考虑这个问题的最佳解决方案。< /P>
1.字典
Python字典没有排序。如果我有这样一本字典:
dictionary = {"one": 1, "two": 2}
然后我循环查字典。项目,我可以先得到1:1,或者我可以先得到2:2。我不知道
每个Python字典都隐式地有两个与之关联的列表:一个键列表和一个值列表。您可以让他们列出以下内容:
print(list(dictionary.keys()))
print(list(dictionary.values()))
这些列表确实有顺序。这样就可以进行分类了。当然,这样做不会改变原来的词典
你的代码
您意识到的是,在您的情况下,您只希望根据字典密钥中的第一个IP地址进行排序。因此,您采取的策略大致如下:
ips={}
for key in sresult:
if '-' in key:
l = key.split('-')[0]
ips[l] = key
else:
ips[1] = key
我建立一个新的字典,其中的关键是只有这第一部分。
2.从字典里查一串钥匙。
3.对键列表进行排序。
4查询原始字典中的值
正如您所注意到的,这种方法将在步骤1失败。因为一旦你用截短的键创建了新的字典,你就失去了区分一些最后只是不同的键的能力。每个字典键都必须是唯一的
更好的战略是:
1构建一个函数,该函数可以将完整的ip地址表示为ip_地址对象
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库能够正常工作,到目前为止应该没有问题。代码的其余部分可以按原样使用
第三部分最佳解决方案
每当您处理排序时,总是最容易想到一个简单得多的问题:给定两个项目,我将如何比较它们?Python为我们提供了一种实现这一点的方法。我们要做的是实现两个数据模型方法
__le__
及
让我们试着这样做:
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
现在你可以做:
for key in sorted_dictionary_keys:
print(key)
print(sresults[key])
Python数据模型几乎是Python的定义特性。我建议您阅读一下。您能提供所需的输出吗?所需的输出与按范围中第一个IP排序的原始数据相同。碰巧的是,我给出的例子是按照这个顺序排列的,但是使用这个顺序10.90.0.0-10.90.255.255会排在最后,而事实上10.96<10.102应该排在第一位谢谢你的回答。老实说,我不能说我明白,但在寻求进一步帮助之前,我会尝试理解我能够使用该类创建词典,但是返回的密钥是我认为我没有正确理解解决方案TBH@hairless1尼尔:首先,我要感谢你的耐心和时间,给我解释这一点。我能够实施这些解决方案,多亏了您的详细解释,我学到了很多东西
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])