DataTable、List、PLINQ使用groupby进行分组和分组统计;List、DataTable查询筛选方法


DataTable分组统计:

//使用linq to DataTable group by实现
var query = from t in dt.AsEnumerable()
            group t by new { t1 = t.Field<string>("name"), t2 = t.Field<string>("sex") } into m
            select new
            {
                name = m.Key.t1,
                sex = m.Key.t2,
                score = m.Sum(n => n.Field<decimal>("score"))
            };
if (query.ToList().Count > 0)
{
    query.ToList().ForEach(q =>
    {
        Console.WriteLine(q.name + "," + q.sex + "," + q.score);
    });
} 
//分组统计按次数排序
Dictionary<string, string> dicProjectExpectFiveParam = listProject.GroupBy(x => new { x.LHCodeID, x.ParamName })
                                                                           .Where(p => !sFiveParam.Contains(p.Key.LHCodeID))
                                                                           .Select(group => new { group.Key, LHCodeIDCount = group.Count() })
                                                                           .OrderByDescending(t => t.LHCodeIDCount)
                                                                           .ToDictionary(o => o.Key.LHCodeID, p => p.Key.ParamName);

DataTable去除重复的方法:

一、ToTable方法来自动过滤所有重复行的数据,代码如下:

DataTable dt = "您的来源dt"; 
DataTable dt_new = dt.DefaultView.ToTable(true, "关键列1", "关键列2");

dt_new中存储的就是我们想要的所有不重复行的数据了。

public string[] GetNamesFromDataTable(DataTable dataTable)
{
            DataView dv = dataTable.DefaultView;
            dataTable = dv.ToTable(true, "Name");
            string[] names = new string[dataTable.Rows.Count];
            for (int i = 0; i < names.Length;i++)
            {
                names[i] = dataTable.Rows[i][0].ToString();
            }
            return names;
}


讲解:
1.DefaultView的返回类型是DataView,而DataView的定义就是:
表示用于排序、筛选、搜索、编辑和导航的System.Data.DataTable的可绑定数据的自定义视图。
所以我们在要用到对DataTable进行排序、筛选、搜索、编辑和导航操作时,就要想到用DataView.

2.public DataTable ToTable(bool distinct, params string[] columnNames)方法:
从参数名我们就可以猜出它的意思了。
distinct:表示返回的Data.DataTable是否包含所有列都具有不同值的行,默认为false。
columnNames:表示要包括在返回的System.Data.DataTable中的列名的列表。如果distinct为true,则它会根据columnNames指定的列名进行筛选过滤。

二、

namespace ConsoleApplication2 
{ 
    class Program 
    { 
        static void Main(string[] args) 
        { 
            DataTable tbl = new DataTable(); 
            tbl.Columns.Add("Id", typeof(System.Int32)); 
            tbl.Columns.Add("City", typeof(System.String)); 
            tbl.Columns.Add("Province", typeof(System.String)); 

            tbl.Rows.Add(1, "武汉", "湖北"); 
            tbl.Rows.Add(2, "应城", "湖北"); 
            tbl.Rows.Add(3, "武汉", "湖北"); 

            IEnumerable <DataRow> r = tbl.AsEnumerable().Distinct(new CityComparer()); 

            //到这一步,r里就是去重复的记录了 
            foreach (var item in r) 
            { 
                Console.WriteLine(item["Id"] + "" + item["City"] + "" + item["Province"]); 
            } 

            Console.ReadLine(); 
        } 
        
    } 

    class CityComparer : IEqualityComparer <DataRow> 
    { 
        public bool Equals(DataRow r1, DataRow r2) 
        { 
            return r1["City"] == r2["City"]; 
        } 

        public int GetHashCode(DataRow obj) 
        { 
            return obj.ToString().GetHashCode(); 
        } 
    } 
}

三、

DataTable sourceDT = new DataTable("Table1");
            sourceDT.Columns.Add("Id", System.Type.GetType("System.String"));
            sourceDT.Columns.Add("Name", System.Type.GetType("System.String"));
            sourceDT.Columns.Add("Age", System.Type.GetType("System.Int32"));
            sourceDT.Columns.Add("Sex", System.Type.GetType("System.String"));
 
            sourceDT.Rows.Add(new object[] { "10001", "李一", 24, "" });
            sourceDT.Rows.Add(new object[] { "10001", "王二", 23, "" });
      
            var groups = sourceDT.AsEnumerable().GroupBy(t => t["Id"].ToString());
            foreach (var group in groups)
            {
                if (group.Count() > 1)
                {
                    foreach (var row in group)
                    {
                        sourceDT.Rows.Remove(row);
                    }
                }
            }

 DataTable中AsEnumerable与Cast类似,都可转为Linq统计、排序等;

//运用LinQ,将DataTable转换为集合,再调用集合自带的排序方法进行排序
foreach (DataRow s in dt.Rows.Cast<DataRow>().OrderBy(r => int.Parse(r["Age"].ToString())))
{
  Response.Write(s["Age"].ToString() + "--" + s["Name"].ToString() + "<br/>");
}
//运用Linq将DataTable转换为集合进行分页(拆分Table)
int PageSize = 65536;
int totalCount = Convert.ToInt32(dtDataAll.Rows.Count);
int totalPage = Convert.ToInt32(Math.Ceiling((double)totalCount / PageSize));
var dtDataAllTemp = dtDataAll.AsEnumerable();
for (var i = 0; i<totalPage; i++)
{
    DataTable dtNew = dtDataAllTemp.Skip(i * PageSize).Take(PageSize).CopyToDataTable();
}

 

List委托

List<Act_TypeListInfo> listFind = listAllTZ.FindAll(delegate( Act_TypeListInfo f){
                        return f.MainID == iMainId && f.KeyName == info.ColKeyName && f.CompID == iCompID);
                    });

 

//linq多表关联分组排序统计
var temp = from ta in areaList
        join tb in StationList on ta.AreaID equals tb.AreaID
        join tc in dcMNComple on tb.MN equals tc.Key into temp1
        //orderby ta.AreaID 
        group temp1 by new { AreaName = ta.AreaName, AreaID = ta.AreaID } into temp2
           select new
           {
             AreaName = temp2.Key.AreaName,
             AreaID = temp2.Key.AreaID,
             MNCount = temp2.Count(),
             Comple = temp2.Sum(s => s.Sum(t => t.Value))
           };

 分组后遍历

List<Cart_Model> list_CartModel = new List<Cart_Model>();  
IEnumerable<IGrouping<string, Cart_Model>> query = list_CartModel.GroupBy(pet => pet.ShopId, pet => pet);  
foreach (IGrouping<string, Cart_Model> info in query)  
{  
  List<Cart_Model> sl = info.ToList<Cart_Model>();//分组后的集合                  
  //也可循环得到分组后,集合中的对象,你可以用info.Key去控制  
  foreach (KqiPageSetupInfo set in sl)   
  {   
  }   
                
}  

 

//从List中查找另一个List的匹配项
var mnList = listFind.Where(d => listYQ.Select(d1 => d1.YQID).Contains(d.YQID)).ToList();
//或 (FindAll)
var mnList = listFind.Where(delegate (T_MNYQInfo f)
{
    foreach (var itemYq in listYQ)
    {
        if (f.YQID == itemYq.YQID)
        {
            return true;
        }
    }
    return false;
}).ToList();

 

//List中查找不为空的数据,去除重复
var qu = list.Where(x => x.DataTime.HasValue).Select(y => y.DataTime.Value).OrderByDescending(z => z).Distinct();
            var listDT = qu.ToList();

 

//List中按两个值排序 OrderBy先排序
List = List.OrderBy(p => p.id).ThenBy(p => p.sid).ToList();

 

//List分页 DataPager1.CurrentPageIndex当前页码 PageSize分页大小
var curMNList = mnList.Skip(PageSize * (DataPager1.CurrentPageIndex - 1)).Take(PageSize).ToList();

 

List分组

            //时间分组模式
            Func<DataEntity, DateTime> groupBy1 = x => x.DataTime.Date;
            Func<DataEntity, DateTime> groupBy2 = x => new DateTime(x.DataTime.Year, x.DataTime.Month, 1);
            Func<DataEntity, DateTime> groupBy3 = x => new DateTime(x.DataTime.Year, 1, 1);
            //如果指定了时间间隔,就用开始时间,按照特定间隔来分组
            if (span > 1)
            {
                dtStart = dtStart.Date;
                groupBy1 = x => dtStart.AddDays(((x.DataTime.Date - dtStart).Days / span) * span);
                groupBy2 = x => new DateTime(dtStart.Year, dtStart.Month + ((x.DataTime.Month - dtStart.Month) / span) * span, 1);
                groupBy3 = x => new DateTime(dtStart.Year + ((x.DataTime.Year - dtStart.Year) / span) * span, 1, 1);
            }
            var groupByChoice = groupByType == 1 ? groupBy1 : (groupByType == 2 ? groupBy2 : groupBy3);

            var luTime = grMN.ToLookup(groupByChoice);

 

/*List对比所有项,判断 listMN1是否所有项存在于 listMN2*/
 List<string> listMN1 = new List<string>(){
                "399435XYX00003",
                "399435XYX00001",
            };
 List<string> listMN2 = new List<string>(){
                "399435XYXKL117",
                "399435XYX00003",
        };

if (listMN1.All(listMN2.Contains))    //true

 

///深度拷贝
public void ListDemo_B()
        {
            var listA = new List<int> { 2, 5, 6, 8, 23, 56, 4 };
            var listB = new List<int>();

            using (MemoryStream ms = new MemoryStream())
            {
                BinaryFormatter bf = new BinaryFormatter();
                bf.Serialize(ms, listA);
                ms.Position = 0;
                listB = (List<int>)bf.Deserialize(ms);
            }            
        }
///使用序列化与反序列化
public void ListDemo_D()
        {
            var listA = new List<int> { 2, 5, 6, 8, 23, 56, 4 };
            var listB = JsonConvert.DeserializeObject<List<int>>(JsonConvert.SerializeObject(listA));
        }

 

//并行化处理两个集合
//PLINQ 的 Zip 方法提供了同时遍历两个集合并进行结合元算的方法,并且它可以与其他查询处理操作结合,实现非常复杂的机能。
public static IEnumerable<T> Zipping<T>(IEnumerable<T> a, IEnumerable<T> b)
{
    return
        a
        .AsParallel()
        .AsOrdered()
        .Select(element => ExpensiveComputation(element))
        .Zip(
            b
            .AsParallel()
            .AsOrdered()
            .Select(element => DifferentExpensiveComputation(element)),
            (a_element, b_element) => Combine(a_element,b_element));
}

//示例中的两个数据源能够并行处理,当双方都有一个可用元素时提供给 Zip 进行后续处理(Combine)。

//Parallel.ForEach 也能实现类似的 Zip 处理:

public static IEnumerable<T> Zipping<T>(IEnumerable<T> a, IEnumerable<T> b)
{
    var numElements = Math.Min(a.Count(), b.Count());
    var result = new T[numElements];
    Parallel.ForEach(a,
        (element, loopstate, index) =>
        {
            var a_element = ExpensiveComputation(element);
            var b_element = DifferentExpensiveComputation(b.ElementAt(index));
            result[index] = Combine(a_element, b_element);
        });
    return result;
}

ParallelLoopState.Stop() 提供了退出循环的方法,这种方式要比其他两种方法更快。这个方法通知循环不要再启动执行新的迭代,并尽可能快的推出循环。

ParallelLoopState.IsStopped 属性可用来判定其他迭代是否调用了 Stop 方法。

ParallelLoopState.Break() 通知循环继续执行本元素前的迭代,但不执行本元素之后的迭代。最前调用 Break 的起作用,并被记录到 ParallelLoopState.LowestBreakIteration 属性中。这种处理方式通常被应用在一个有序的查找处理中,比如你有一个排序过的数组,你想在其中查找匹配元素的最小 index,

Environment.ProcessorCount 获取最大线程数

//预执行1500w(<)条记录
    Parallel.For(0, 15000000, (i) =>
    {
         Console.WriteLine("ThreadProc: {0}", i);
    });

 

//Parallel设置最大线程数、跳出循环以及终止循环
Parallel.ForEach(list,new ParallelOptions(){ MaxDegreeOfParallelism=2}, (p, state1) =>
            { 
                Invoke(p);
                state1.Break();//Break用于根据条件过滤循环,Break不是Continue,不要搞混了!Break是执行完现有的迭代后跳出!
                state1.Stop();//Stop方法用于退出Paraller循环,表示立刻退循环,cease=终止
                return; //注意:不论是Break还是Stop方法,后面的return语句是必须的,否则当前循环体第13行的语句还是会被执行。
            });

 

AsParallel并行执行
WithDegreeOfParallelism指定并行度--为了不让并行计算占用全部的硬件线程,或许可能要留一个线程做其他事情。

var query2 = (from n in dic.Values.AsParallel().WithDegreeOfParallelism(Environment.ProcessorCount - 1)
          where n.Age > 20 && n.Age < 25
                 orderby n.CreateTime descending
                 select n).ToList();

 

 

 收集整理,非原创

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM