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