如何使用c#对IP地址列表进行排序

23

我有一个IP地址列表如下:

192.168.1.5
69.52.220.44
10.152.16.23
192.168.3.10
192.168.1.4
192.168.2.1

我正在寻找一种方法来对这个列表进行排序,使其符合以下顺序

10.152.16.23
69.52.220.44
192.168.1.4
192.168.1.5
192.168.2.1
5个回答

54

这可能看起来像一个hack,但它确实做到了你所需的:

var unsortedIps =
    new[]
    {
        "192.168.1.4",
        "192.168.1.5",
        "192.168.2.1",
        "10.152.16.23",
        "69.52.220.44"
    };

var sortedIps = unsortedIps
    .Select(Version.Parse)
    .OrderBy(arg => arg)
    .Select(arg => arg.ToString())
    .ToList();

5
@Norbert - 在发表评论之前,请尝试运行一下代码。我在发布之前实际上已经检查了结果。 - Alex Aza
1
@Alex 不错的解决方案,谢谢啊。 - Cracker
更紧凑的版本:unsortedIps.OrderBy(Version.Parse).ToList() - Falko
请注意,Version.Parse 方法仅在 .Net Framework 4 中添加,因此如果使用较早版本的框架,则此解决方案将无法工作。 - Steven Rands
2
我有一个 List<IPAddress>,并按照以下方式进行了排序:lstIp = lstIp.OrderBy(i => new Version(i.ToString())).ToList(); - tolsen64
显示剩余3条评论

11

您可以像这样将每个IP地址转换为整数...

69.52.220.44 =>

69 * 255 * 255 * 255 +
52 * 255 * 255 +
220 * 255 +
44

然后按整数表示进行排序。


3
通过这种计算,0.0.0.2550.0.1.0的值相同,但它们应该是不同的。乘数应该是256而不是255。参见维基百科:“例如,点分十进制表示法的IP地址192.0.2.235代表32位十进制数3221226219。” 192.0.2.235确实等于192*256*256*256 + 2*256 + 235,即3221226219。如果您使用上述公式,则会得到192*255*255*255 + 2*255 + 235 = 3183624745。 - Patrick Mevzek
@PatrickMevzek 是正确的。一个字节有256个值,你应该乘以值的数量,而不是更高的那个。 - Riwels
请确保使用32位无符号整数! - thinkOfaNumber

3
你可能也会发现这个函数很有用。
public static class ExtensionMethods
{
  public static int CompareTo(this IPAddress x, IPAddress y)
  {
    var result = x.AddressFamily.CompareTo(y.AddressFamily);
    if (result != 0)
      return result;

    var xBytes = x.GetAddressBytes();
    var yBytes = y.GetAddressBytes();

    var octets = Math.Min(xBytes.Length, yBytes.Length);
    for (var i = 0; i < octets; i++)
    {
      var octetResult = xBytes[i].CompareTo(yBytes[i]);
      if (octetResult != 0)
        return octetResult;
    }
    return 0;
  }
}

2

不需要任何技巧就可以得到简单的解决方案。只需将地址段分割,用零填充段,然后将它们重新组合在一起。将这个一行的静态方法放入一个静态类中,像这样:

public static class StringHelper
{
    public static string IpAddressLabel(string ipAddress)
        => string.Join(".", ipAddress.Split('.').Select(part => part.PadLeft(3, '0')));
}

然后随意调用它:

 => new[] {"192.168.1.100", "192.168.1.1", "192.168.1.19"}
      .OrderBy(ip => StringHelper.IpAddressLabel(ip));

此外,在需要可排序标签时,这可以用作文件名或其他地方的标签:

192.168.001.001.log
192.168.001.019.log
192.168.001.100.log

0

你可以使用Array.Sort函数,配合我们将创建的用于比较两个IP的函数。

//ips is string array
Array.Sort(ips, IpCompare);

然后将此函数放入代码中。

private static int IpCompare(string x, string y)
    {
        string ip1 = x + '.', ip2 = y + '.';
        string xSection = "", ySection = "";
        for (int i = 0; i < ip1.Length && i < ip2.Length; i++)
        {
            if (ip1[i] == '.' && ip2[i] == '.')
            {
                if (xSection != ySection)
                    return int.Parse(xSection) - int.Parse(ySection);
                xSection = ""; // Start compare the next section
                ySection = "";
            }
            else if (ip1[i] == '.') return -1; //The first section is smaller because it's length is smaller
            else if (ip2[i] == '.') return 1;
            else
            {
                xSection += ip1[i];
                ySection += ip2[i];
            }
        }
        return 0; 
        //If we would find any difference between any section it would already return something.
        //so that mean that both IPs are the same
   }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接