Python:对作为字典键的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

我有一个字典,它将IP地址范围作为键,用于在上一步中消除重复,并将某些对象作为值。这里有一个例子

词典的一部分sresult:

有上万行,我想按密钥中的IP地址正确排序

我尝试根据范围分隔符拆分密钥-以获得单个IP地址,该地址可以按如下方式排序:

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])