Linq / Lambda OrderBy委托列出IP地址的

给定List ips = new List();

我需要按逻辑顺序对IP地址列表进行排序(即“192.168.0.2”出现在“192.168.0.100”之前)。

目前(并且正确地,按字母顺序排列)列表是否包含:

 192.168.0.1 192.168.0.2 192.168.0.10 192.168.0.200 

ips.OrderBy(p => p)返回:

 192.168.0.1 192.168.0.10 192.168.0.2 192.168.0.200 

你需要做一个比较器:(测试)

 class IPComparer : IComparer { public int Compare(string a, string b) { return Enumerable.Zip(a.Split('.'), b.Split('.'), (x, y) => int.Parse(x).CompareTo(int.Parse(y))) .FirstOrDefault(i => i != 0); } } 

然后你可以写

 ips.OrderBy(p => p, new IPComparer()) 

我会像这样为System.Net.IPAddress创建一个比较器

 class IPAddressComparer : IComparer { public int Compare(IPAddress x, IPAddress y) { byte[] first = x.GetAddressBytes(); byte[] second = y.GetAddressBytes(); return first.Zip(second, (a, b) => a.CompareTo(b)) .FirstOrDefault(c => c != 0); } } 

然后按以下步骤操作:

 var list = new List() { "192.168.0.1", "192.168.0.10", "192.168.0.2", "192.168.0.200" }; var sorted = list.OrderBy(s => IPAddress.Parse(s), new IPAddressComparer()); 

您可以将其拆分为4个整数值,并按顺序依次排序:

  var results = ips .Select(s => string.Split('.').Select(str => int.Parse(str)).ToArray() ) .OrderBy(intArray => intArray[0]) .ThenBy(intArray => intArray[1]) .ThenBy(intArray => intArray[2]) .ThenBy(intArray => intArray[3]) .Select(intArray => string.Join(".", intArray) ); 

这个非常优雅(如果你使用TryParse则失败certificate):

 var sorted2 = from ip in ips let addressBytes = IPAddress.Parse(ip).GetAddressBytes() orderby addressBytes[0], addressBytes[1], addressBytes[2], addressBytes[3] select ip; 

只要IP4地址, addressBytes数组的长度为4。 否则你应该考虑长度……

我写了一个IPv6的IpComparer。 Howel的变种不起作用。

这是比较者:

 ///  /// Compares two ip addresses. /// http://stackoverflow.com/questions/4785218/linq-lambda-orderby-delegate-for-liststring-of-ip-addresses ///  public class IpComparer : IComparer { ///  /// Compares two objects and returns a value indicating whether one is less than, equal to, or greater than the other. ///  /// ///  /// A signed integer that indicates the relative values of  and , as shown in the following table. /// Value Meaning Less than zero is less than . /// Zero equals . /// Greater than zero  is greater than . ///  /// The first object to compare.The second object to compare. public int Compare(IPAddress x, IPAddress y) { if (ReferenceEquals(x, null)) { throw new ArgumentNullException("x"); } if (ReferenceEquals(y, null)) { throw new ArgumentNullException("y"); } byte[] bytesOfX = x.GetAddressBytes(); byte[] bytesOfY = y.GetAddressBytes(); return StructuralComparisons.StructuralComparer.Compare(bytesOfX, bytesOfY); } } 

这里是一个unit testing:

 [TestFixture] public class IpComparerTest : AbstractUnitTest { private IpComparer _testee; [SetUp] public void Setup() { _testee = new IpComparer(); } [TestCase("10.156.35.205", "10.156.35.205")] [TestCase("0.0.0.1", "0.0.0.1")] [TestCase("2001:0db8:0000:08d3:0000:8a2e:0070:7344", "2001:db8:0:8d3:0:8a2e:70:7344")] [TestCase("2001:0db8:0:0:0:0:1428:57ab", "2001:db8::1428:57ab")] [TestCase("2001:0db8:0:0:8d3:0:0:0", "2001:db8:0:0:8d3::")] [TestCase("::ffff:127.0.0.1", "::ffff:7f00:1")] public void Compare_WhenIpsAreEqual_ThenResultIsZero(string ip1, string ip2) { // Arrange IPAddress x = IPAddress.Parse(ip1); IPAddress y = IPAddress.Parse(ip2); // Act and Assert Assert.That(_testee.Compare(x, y), Is.EqualTo(0)); } [TestCase("10.156.35.2", "10.156.35.205")] [TestCase("0.0.0.0", "0.0.0.1")] [TestCase("1001:0db8:85a3:08d3:1319:8a2e:0370:7344", "2001:0db8:85a3:08d3:1319:8a2e:0370:7344")] [TestCase("2001:0db8:85a3:08d3:1319:8a2e:0370:7343", "2001:0db8:85a3:08d3:1319:8a2e:0370:7344")] public void Compare_WhenIp1IsLessThanIp2_ThenResultIsLessThanZero(string ip1, string ip2) { // Arrange IPAddress x = IPAddress.Parse(ip1); IPAddress y = IPAddress.Parse(ip2); // Act and Assert Assert.That(_testee.Compare(x, y), Is.LessThan(0)); } [TestCase("10.156.35.205", "10.156.35.2")] [TestCase("0.0.0.1", "0.0.0.0")] [TestCase("3001:0db8:85a3:08d3:1319:8a2e:0370:7344", "2001:0db8:85a3:08d3:1319:8a2e:0370:7344")] [TestCase("2001:0db8:85a3:08d3:1319:8a2e:0370:7345", "2001:0db8:85a3:08d3:1319:8a2e:0370:7344")] public void Compare_WhenIp1IsGreaterThanIp2_ThenResultIsGreaterThanZero(string ip1, string ip2) { // Arrange IPAddress x = IPAddress.Parse(ip1); IPAddress y = IPAddress.Parse(ip2); // Act and Assert Assert.That(_testee.Compare(x, y), Is.GreaterThan(0)); } } 

我希望这个解决方案是正确的。 我不是IPv6的专家。

这是一个老问题,但我正在查找IP Comparer的,它出现了。 我想要一些适用于IPv6的东西,尽管如此,一旦我得到它,我想我会在这里为下一个搜索它的人添加它。 就像SLaks的回答一样,我同意IComparer可能是最好的。

 public class IPComparer : IComparer { public int Compare(IPAddress x, IPAddress y) { if (ReferenceEquals(x, null)) throw new ArgumentNullException("x"); if (ReferenceEquals(y, null)) throw new ArgumentNullException("y"); return BitConverter.ToUInt32(x.GetAddressBytes().Reverse().ToArray(),0) .CompareTo(BitConverter.ToUInt32(y.GetAddressBytes().Reverse().ToArray(),0)); } } 

没有什么花哨但它应该有效。