.net Framework提供了大量集合(collection)类,我们这里以最常用List为例,总结他的排序和查询。
List<T>是一个泛型集合,相比ArrayList,不用进行每次操作的装箱拆箱工作。
一、集合的排序
如果T为值类型可以直接使用sort():
List<int> Numbers=new List<int> (){4,5,1,8,3,2,7};
Numbers.Sort();
如果T为一个引用类型,如自己设定的类,将有以下两种方法:
1.将此类继承IComparable接口:
public enum KindOfDuck
{
Mallard, Muscovy, Decoy
}
public class Duck:IComparable<Duck>
{
public int Size;
public KindOfDuck Kind;
public int CompareTo(Duck other)
{
//从小到大排列,当前鸭子与更小的鸭子比较时,返回一个负数
return this.Size.CompareTo(other.Size);
}
}
class Program
{
static void Main(string[] args)
{
List<Duck> Ducks = new List<Duck>()
{
new Duck(){Kind=KindOfDuck.Mallard,Size=17},
new Duck(){Kind=KindOfDuck.Mallard,Size=18},
new Duck(){Kind=KindOfDuck.Mallard,Size=14},
new Duck(){Kind=KindOfDuck.Mallard,Size=11},
new Duck(){Kind=KindOfDuck.Mallard,Size=14},
new Duck(){Kind=KindOfDuck.Mallard,Size=13},
};
Ducks.Sort();
Console.Read();
}
}
2.写一个单独的类帮助List排序,实现IComparer接口:
public class Duck
{
public int Size;
public KindOfDuck Kind;
}
public class DuckCompare_bySize : IComparer<Duck>
{
public int Compare(Duck x, Duck y)
{
return x.Size.CompareTo(y.Size);
}
}
public enum KindOfDuck
{
Mallard, Muscovy, Decoy
}
class Program
{
static void Main(string[] args)
{
List<Duck> Ducks = new List<Duck>()
{
new Duck(){Kind=KindOfDuck.Mallard,Size=17},
new Duck(){Kind=KindOfDuck.Mallard,Size=18},
new Duck(){Kind=KindOfDuck.Mallard,Size=14},
new Duck(){Kind=KindOfDuck.Mallard,Size=11},
new Duck(){Kind=KindOfDuck.Mallard,Size=14},
new Duck(){Kind=KindOfDuck.Mallard,Size=13},
};
DuckCompare_bySize dc = new DuckCompare_bySize();
Ducks.Sort(dc);
}
}
二、集合的查找
利用LINQ语法查询,会使集合的查询非常简单,看下面这个简单的例子:
class Program
{
static void Main(string[] args)
{
List<Book> books = new List<Book>()
{
new Book(){Number=1,Name="cq"},
new Book(){Number=2,Name="cq"},
new Book(){Number=3,Name="c"}
};
//要得到
//List<Book> result = books.FindAll(book => book.Name == "cq");
foreach (Book book in books.Where(book => book.Name == "cq"))
{
Console.WriteLine(book.Number);
}
Console.Read();
}
}
public class Book
{
public int Number { get; set; }
public string Name { get; set; }
}
这里的where方法就是LINQ的方法,下面是where的定义
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);
this关键字是扩展方法,原本的LIST在没引用lINQ时是没有这个where方法的,这个扩展方法在静态类中声明,定义一个静态方法,其中第一个参数定义是它的扩展类型。
这里举个简单的例子,现在List没有Foreach方法,我们扩展一下:
class Program
{
static void Main(string[] args)
{
List<Book> books = new List<Book>()
{
new Book(){Number=1,Name="cq"},
new Book(){Number=2,Name="cq"},
new Book(){Number=3,Name="c"}
};
books.Where(book => book.Name == "cq").ForEach
(
book => { Console.WriteLine(book.Number); }
);
Console.Read();
}
}
public class Book
{
public int Number { get; set; }
public string Name { get; set; }
}
public static class IEnumerableExtension
{
public static void ForEach<T>(this IEnumerable<T> enumeration, Action<T> action)
{
foreach (var item in enumeration)
{
action(item);
}
}
}
这里再说明一下Func<TSource, bool> predicate这个委托,它的定义为:
public delegate TResult Func<in T, out TResult>(T arg)
如果没有这个委托,传统的实现方法:
using System;
delegate string ConvertMethod(string inString);
public class DelegateExample
{
public static void Main()
{
// Instantiate delegate to reference UppercaseString method
ConvertMethod convertMeth = UppercaseString;
string name = "Dakota";
// Use delegate instance to call UppercaseString method
Console.WriteLine(convertMeth(name));
}
private static string UppercaseString(string inputString)
{
return inputString.ToUpper();
}
}
使用这个委托会使代码变得更简洁:
using System;
public class LambdaExpression
{
public static void Main()
{
Func<string, string> convert = s => s.ToUpper();
string name = "Dakota";
Console.WriteLine(convert(name));
}
}
后面链接文章有一些利用LINQ的算法:.net3.5下使用LINQ递归算法实现简洁代码