c# List 里面的Linq方法
虽然List里的linq方法(其实是Enumarable的)大部分比较简单 ,但是如果能够灵活运用也是提高code质量,可读性和coding能力的有效途径。而且其中有些方法,例如 Join, 光看注释可能会有点懵。 最近把他们go through了一遍。代码如下。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Linq;
using System.Collections.ObjectModel;
using System.Collections;
namespace ListMethodTest
{
public class TestItem
{
public int number { get; set; }
public string str { get; set; }
//used for SelectMany
public List<string> children { get; set; }
public override int GetHashCode()
{
return number;
}
}
public class InnerClass
{
public int id { get; set; }
public string name { get; set; }
}
public class ChildTestItem : TestItem
{ }
public class ConvertTest
{
public int a { get; set; }
}
public partial class _Default : System.Web.UI.Page
{
List<TestItem> lst1 = new List<TestItem>();
protected void Page_Load(object sender, EventArgs e)
{
lst1.Add(new TestItem() { number = 3, str = "dsdfsf", children = new List<string>() { "c1", "c2" } });
lst1.Add(new TestItem() { number = 1, str = "csdfsdf", children = new List<string>() { "c3", "c4" } });
lst1.Add(new TestItem() { number = 2, str = "aasdfsdf" });
lst1.Add(new TestItem() { number = 2, str = "222" });
int part = 3;
switch (part)
{
case 1: Part1();break;
case 2: Part2(); break;
case 3: Part3(); break;
default: break;
}
}
private void Part3()
{
int sum = lst1.Sum(x => x.number);
List<TestItem> take = lst1.Take(3).ToList();
//同样 take前面的
List<TestItem> takewhile = lst1.TakeWhile(x => x.number == 3).ToList();
//key必须唯一
// Dictionary<int,TestItem> toDic= lst1.ToDictionary(x => x.number);
//Ilookup:IEnumerable<TElement> this[TKey key] { get; } 所以可以有重key
ILookup<int, TestItem> lookup = lst1.ToLookup(x => x.number);
//lst1.TrimExcess();
bool trueforall = lst1.TrueForAll(x => x.number > -1);
List<TestItem> where = lst1.Where(x => x.number == 2).ToList();
}
void Part2()
{
// 里面的 item和原来的是一个引用,即便 不重写GetHashCode
List<TestItem> getR = lst1.GetRange(1, 2);
IEnumerable<IGrouping<int, TestItem>> gb = lst1.GroupBy(x => x.number);
int io = lst1.IndexOf(lst1[1]);
lst1.Insert(0, new TestItem() { number = 0, str = "00" });
List<TestItem> toInsert = new List<TestItem>()
{
new TestItem() { number = 0, str = "InsertRange0"},
new TestItem() { number = 2, str = "InsertRange1" },
new TestItem() { number = 9, str = "InsertRange2" },
};
//lst1.InsertRange(0, toInsert);
//返回 lst1中与 toInsert 相等的 元素
List<TestItem> Intersect = lst1.Intersect(toInsert, new DistinctTest()).ToList();
List<InnerClass> inner = new List<InnerClass>() {
new InnerClass(){ id=1, name="name1"},
new InnerClass(){ id=2, name="name2"},
new InnerClass(){ id=3, name="name3"},
};
// 2个list的 TKEY 类型必须一致, 返回 key相等的组合 ,其实就是 key相等的 inner join
// 最后一个委托只是根据组合 生成 返回的结果
IEnumerable join = lst1.Join(inner, x => x.number, i => i.id, (a, b) => new { a.number, a.str, b.id, b.name });
// 类似 dictionary, lst1为key, 匹配的 InnerClass 的集合为value ,即使集合count为0(没有匹配) ,也会组合
IEnumerable gj = lst1.GroupJoin(inner, x => x.number, i => i.id, (a, b) => new { id = a.number, name = a.str, lst = b });
IEnumerable zip = lst1.Zip(inner, (x, y) => new { x.number, x.str, y.id, y.name });
TestItem last = lst1.Last(x => x.number == 2);
int lindex = lst1.LastIndexOf(lst1[2]);
int max = lst1.Max(x => x.number);
int min = lst1.Min(x => x.number);
//lst1.Add(new ChildTestItem());
//IEnumerable<ChildTestItem> ot= lst1.OfType<ChildTestItem>();
List<TestItem> ob = lst1.OrderBy(x => x.str).ToList();
//lst1.Sort((a, b) => {
// if( a.number< b.number) return -1;
// else if( a.number == b.number) return 0;
// else return 1;
// } );
// TestItem temp =lst1[0];
// bool remove = lst1.Remove(temp);
// int ra= lst1.RemoveAll(x => x.number == 2);
// lst1.RemoveAt(2);
//lst1.RemoveRange(2, 2);
//lst1.Reverse();
// select 是变形用的 ,这个词太唬人了,别被他的外表所蒙蔽
IEnumerable select = lst1.Select(x => new { id = x.number, name = x.str, g = Guid.NewGuid() });
IEnumerable select1 = lst1.Select((x, y) => new { id = x.number, name = x.str, index = y, g = Guid.NewGuid() });
//flatten IEnumerable{"c1","c2","c3","c4"}
IEnumerable SelectMany = lst1.SelectMany(x => x.children == null ? new List<string>() : x.children);
List<TestItem> s1 = new List<TestItem>()
{
new TestItem(){ number=1 ,str="sdf" }
};
List<TestItem> s2 = new List<TestItem>()
{
new TestItem(){ number=1 }
};
//个数不一样肯定 false
bool se = s1.SequenceEqual(s2, new DistinctTest());
List<TestItem> union = s1.Union(s2).ToList();
//不single的话 throw exception
//TestItem singe = lst1.Single(x => x.number ==2);
List<TestItem> skip = lst1.Skip(2).ToList();
//注意 bypass 前面的element
List<TestItem> SkipWhile = lst1.SkipWhile(x => x.number == 0).ToList();
}
void Part1()
{
// ( (item 1,2 的结果 ) 和item 3的结果)和item 4的结果
TestItem agg = lst1.Aggregate((i, j) => { i.number += j.number; return i; });
bool all = lst1.All(i => i.str.Contains("c"));
bool any = lst1.Any(i => i.str.Contains("c"));
ParallelQuery p = lst1.AsParallel();
IQueryable<TestItem> q = lst1.AsQueryable();
var query = from ti in q where ti.number == 2 select ti;
ReadOnlyCollection<TestItem> readonlylst = lst1.AsReadOnly();
double average = lst1.Average(i => i.number);
int index = lst1.BinarySearch(new TestItem() { number = 1, str = "123123" }, new CompareClass());
//如果lst1是非泛型的集合 ,转换之后就可以用泛型的方法啦! where, any ,select , all等
IEnumerable<TestItem> castedLst = lst1.Cast<TestItem>();
List<TestItem> lsttoConcat = new List<TestItem>() { new TestItem() { number = 4 } };
List<TestItem> concatedLst = lst1.Concat(lsttoConcat).ToList();
TestItem t = new TestItem() { number = 4 };
lst1.Add(t);
//bool contains = lst1.Contains<TestItem>(t);
bool contains = lst1.Contains<TestItem>(new TestItem() { number = 4 });
//bool contains = lst1.Contains<string>("sdfsdf"); it's wrong!
List<ConvertTest> convertedLst = lst1.ConvertAll(i => new ConvertTest() { a = i.number });
TestItem[] arr = new TestItem[10];
lst1.CopyTo(arr, 3);
//下面defLst count 为 0
IEnumerable<TestItem> defLst = lst1.DefaultIfEmpty();
IEnumerable<TestItem> dsicLst = lst1.Distinct();
lst1.Add(new TestItem() { number = 4, str = "sdfsd" });
IEnumerable<TestItem> dsicLst1 = lst1.Distinct<TestItem>(new DistinctTest());
TestItem elementat = lst1.ElementAt(1);
TestItem elementatORDefault = lst1.ElementAtOrDefault(10);
List<TestItem> toexcept = new List<TestItem>()
{
lst1[2],
lst1[3]
};
IEnumerable<TestItem> exceptedLst = lst1.Except(toexcept);
bool exist = lst1.Exists(i => i.number == 4);
TestItem find = lst1.Find(i => i.number == 4);
List<TestItem> findall = lst1.FindAll(i => i.number == 4);
int fIndex = lst1.FindIndex(i => i.number == 4);
TestItem fLast = lst1.FindLast(i => i.number == 4);
int lastIndex = lst1.FindLastIndex(i => i.number == 4);
TestItem first = lst1.First(x => x.number == 4);
lst1.ForEach(x => x.str = x.number == 4 ? "4" : x.str);
}
}
public class DistinctTest : IEqualityComparer<TestItem>
{
public bool Equals(TestItem x, TestItem y)
{
if (x.number == y.number) return true;
else return false;
}
public int GetHashCode(TestItem obj)
{
//HashCode默认情况就是地址的散列码,跟散列算法有关系,所以默认情况不同对象的hashcode是不一样的,所以要重写TestItem的GetHashCode方法。
//用最简单的方法来说,hashcode就是一个签名。当两个对象的hashcode一样时,两个对象就"有可能"一样。如果不一样的话两个对象就"肯定"不一样。
return obj.GetHashCode();
}
}
public class CompareClass : IComparer<TestItem>
{
public int Compare(TestItem x, TestItem y)
{
if (x.number < y.number) return -1;
else if (x.number == y.number) return 0;
else return 1;
}
}
}