泛型类List<Model>和 DataTable的分组统计

2 篇文章 0 订阅
    项目中在经常会对数据解析并做图标展示,数据获取的方式有很多(文本文件、api、数据库……),大多数情况下我们都会将数据转化为泛型类List或者DataTable两种数据类型并做处理,并绑定在UI界面做各种炫酷的展示,下面我们讲讲这泛型类List和DataTable两种数据源的数据处理吧。
  1. 指定列去重复数据
  • 使用ToTable函数
#region ①ToTable
		DataView pDataView = new DataView(vDataTable);
		string[] pDistinctColumnName = { vTableColumnName, vTableColumnClass };
		DataTable pTempDataViewTable = pDataView.ToTable(true, pDistinctColumnName);
#endregion
  • 使用GroupBy + FirstOrDefault函数
#region ② GroupBy + FirstOrDefault
		DataTable dt_DistinctTable = vDataTable.AsEnumerable()
				.Cast<DataRow>().Distinct()
				.GroupBy(p => new{ 
							Name = p.Field<string>(vTableColumnName), 
							Class= p.Field<string>(vTableColumnClass) 
						})
				.Select(p => p.FirstOrDefault())
				.CopyToDataTable();
#endregion
  • 效果图
  • 去重复前
  • 去重复后
  1. DataTable转换为List<Model>
  • Lamda 表达式写法(推荐)
		List<IGroupByModel> pDistinctDataRowsLamdaToLst = vDataTable.Rows.Cast<DataRow>()
               .GroupBy(dr => new { 
			               Name = dr.Field<string>(vTableColumnName), 
			               Class = dr.Field<string>(vTableColumnClass) 
		               })
               .Select(x => x.FirstOrDefault())
               .AsEnumerable()
               .Select(p => new IGroupByModel() { 
		               Name = p.Field<string>(vTableColumnName), 
		               Class = p.Field<string>(vTableColumnClass) 
		               })
               .ToList<IGroupByModel>();
		var result = from dt in vDataTable.AsEnumerable()
	             group dt by new { 
				             Name = dt.Field<string>(vTableColumnName), 
				             Class = dt.Field<string>(vTableColumnClass) 
			             } 
	             into temp
	             select new IGroupByModel()
	             {
	             	 //https://www.jb51.net/article/70931.htm
	                 Name = temp.Key.Name,//temp.First().Field<string>("Name")
	                 Class = temp.Key.Class,//temp.First().Field<string>("Class")
	             };
	List<IGroupByModel> pDistinctDataRowsLinqToLst = result.ToList<IGroupByModel>();
  1. 分组后相同列数据用“,”拼接
  • 传统方式Foreach or If
	 	string pColumn2Value = string.Empty;
        foreach (GroupByModel pGroupByModelItem in pModelLst)
        {
            if (string.IsNullOrEmpty(pColumn2Value))
            {
                pColumn2Value = pGroupByModelItem.Class == null ? "" 
                	: pGroupByModelItem.Class.ToString();
            }
            else
            {
                pColumn2Value += pGroupByModelItem.Class == null ? "" 
                	: "," + pGroupByModelItem.Class.ToString();
            }
        }
  • 聚合器Aggrate
		string pColumn2Value = string.Empty;
		pColumn2Value = pModelLst.Aggregate("", (a, b) =>
		{
		    if (!string.IsNullOrEmpty(b.Class))
		    {
		        if (a == "")
		        {
		            return b.Class;
		        }
		        a += "," + b.Class;
		        return a;
		    }
		    else
		    {
		        return a;
		    }
		});
  • 效果
  • 聚合前
    聚合前
  • 聚合后
    聚合后
  1. 结合MVVMWPF的实现
  • Model
	public class GroupByModel
    {
        #region 字段、属性
        public string Name { get; set; }
        public string Class { get; set; }
        #endregion

        #region 私有方法
        private static DataTable CreateCustomDataTable(string pColumnNameOne,string pColumnNameTwo)
        {
            try
            {
                DataTable pDataTable = new DataTable();
                pDataTable.Columns.Add(pColumnNameOne, typeof(string));
                pDataTable.Columns.Add(pColumnNameTwo, typeof(string));

                for (int i = 0; i < 3; i++)
                {
                    DataRow pDataRow = pDataTable.NewRow();
                    pDataRow[pColumnNameOne] = "Name" + i;
                    pDataRow[pColumnNameTwo] = "Class" + i;
                    pDataTable.Rows.Add(pDataRow);
                }

                for (int i = 0; i < 3; i++)
                {
                    DataRow pDataRow = pDataTable.NewRow();
                    pDataRow[pColumnNameOne] = "Name" + i;
                    pDataRow[pColumnNameTwo] = "Class" + i + i;
                    pDataTable.Rows.Add(pDataRow);
                }

                for (int i = 0; i < 6; i++)
                {
                    DataRow pDataRow = pDataTable.NewRow();
                    pDataRow[pColumnNameOne] = "Name" + i;
                    pDataRow[pColumnNameTwo] = "Class" + i;
                    pDataTable.Rows.Add(pDataRow);
                }

                return pDataTable;
            }
            catch (Exception ex)
            {
                CommonBasic.Log.BlossLog.AddErrorLog(ex);
                return null;
            }
        }

        #region DataTable
        /// <summary>
        /// 过滤原Table数据,(去重、拼接)返回新建Table数据
        /// </summary>
        /// <param name="vDataTable"></param>
        /// <param name="vTableColumnName"></param>
        /// <param name="vTableColumnClass"></param>
        /// <param name="nameColumnOne"></param>
        /// <param name="nameColumnTwo"></param>
        /// <param name="oDistinctCount"></param>
        /// <returns></returns>
        private static DataTable GetMergeColumDataTable(DataTable vDataTable, string vTableColumnName, string vTableColumnClass, string nameColumnOne, string nameColumnTwo,out int oDistinctCount)
        {
            oDistinctCount = 0;
            try
            {
                if (vDataTable == null || vDataTable.Rows.Count == 0)
                {
                    return null;
                }
                DataTable pDataTable = new DataTable();
                pDataTable.Columns.Add(nameColumnTwo, typeof(string));
                pDataTable.Columns.Add(nameColumnOne, typeof(string));

                #region 去重复数据
                #region ①ToTable
                DataView pDataView = new DataView(vDataTable);
                string[] pDistinctColumnName = { vTableColumnName, vTableColumnClass };
                DataTable pTempDataViewTable = pDataView.ToTable(true, pDistinctColumnName);
                #endregion
                #region ② GroupBy + FirstOrDefault
                DataTable dt_DistinctTable = vDataTable.AsEnumerable().Cast<DataRow>().Distinct().GroupBy(p => new{ Name = p.Field<string>(vTableColumnName), Class= p.Field<string>(vTableColumnClass) }).Select(p => p.FirstOrDefault()).CopyToDataTable();
                #endregion
                #endregion

                #region 按列(vTableColumnName)分组  
                IEnumerable<IGrouping<string, DataRow>> pGroupDataTable = pTempDataViewTable.Rows.Cast<DataRow>().Distinct<DataRow>().GroupBy<DataRow, string>(dr => dr[vTableColumnName].ToString());
                
                foreach (IGrouping<string, DataRow> pGroupDataTableRow in pGroupDataTable)
                {
                    DataRow pDataRow = pDataTable.NewRow();
                    pDataRow[nameColumnOne] = pGroupDataTableRow.Key;

                    string pColumn2Value = string.Empty;

                    #region 相同Key值Value叠加方式一 http://www.bamn.cn/News/views/129
                    //pColumn2Value = pGroupDataTableRow.Aggregate("", (next, dr) =>
                    //{
                    //    if (dr[vTableColumnClass] != null || dr[vTableColumnClass].ToString() != "")
                    //    {
                    //        if (next == "")
                    //        {
                    //            return dr[vTableColumnClass]?.ToString();
                    //        }
                    //        next += "," + dr[vTableColumnClass]?.ToString();
                    //        return next;
                    //    }
                    //    else
                    //    {
                    //        return next;
                    //    }
                    //});
                    #endregion

                    #region 相同Key值Value叠加方式2
                    foreach (DataRow pDataRowItem in pGroupDataTableRow)
                    {
                        if (string.IsNullOrEmpty(pColumn2Value))
                        {
                            pColumn2Value = pDataRowItem[vTableColumnClass] == null ? "" : pDataRowItem[vTableColumnClass].ToString();
                        }
                        else
                        {
                            pColumn2Value += pDataRowItem[vTableColumnClass] == null ? "" : "," + pDataRowItem[vTableColumnClass].ToString();
                        }
                    }
                    #endregion

                    pDataRow[nameColumnTwo] = pColumn2Value;

                    pDataTable.Rows.Add(pDataRow);
                }
                #endregion

                #region 统计数量
                object pObj = vDataTable?.AsEnumerable().Select(r => r[vTableColumnClass].ToString()).Distinct().Count();
                oDistinctCount = Convert.ToInt32(pObj);
                #endregion

                return pDataTable;
            }
            catch (Exception ex)
            {
                CommonBasic.Log.BlossLog.AddErrorLog(ex);
                return null;
            }
        }
        #endregion

        #region List
        private static List<GroupByModel> GetMergeColumDataTableToLst(DataTable vDataTable, string vTableColumnName, string vTableColumnClass, out int oDistinctCount)
        {
            oDistinctCount = 0;

            try
            {
                if (vDataTable == null || vDataTable.Rows.Count == 0)
                {
                    return null;
                }

                List<GroupByModel> pIGroupByModelLst = new List<GroupByModel>();
                #region 转化为Lis thttps://www.cnblogs.com/johnblogs/p/6006867.html  

                #region lamda 表达式写法(推荐)
                List<GroupByModel> pDistinctDataRowsLamdaToLst = vDataTable.Rows.Cast<DataRow>()
                    .GroupBy(dr => new { Name = dr.Field<string>(vTableColumnName), Class = dr.Field<string>(vTableColumnClass) })
                    .Select(x => x.FirstOrDefault())
                    .AsEnumerable().Select(p => new GroupByModel() { Name = p.Field<string>(vTableColumnName), Class = p.Field<string>(vTableColumnClass) }).ToList<GroupByModel>();
                #endregion

                #region Linq写法 最终编译器会把它转化为lamda表达式 https://www.cnblogs.com/hedianzhan/p/9010999.html
                var result = from dt in vDataTable.AsEnumerable()
                             group dt by new { Name = dt.Field<string>(vTableColumnName), Class = dt.Field<string>(vTableColumnClass) } into temp
                             select new GroupByModel()
                             {
                                 Name = temp.Key.Name,//temp.First().Field<string>("Name")//https://www.jb51.net/article/70931.htm
                                 Class = temp.Key.Class,//temp.First().Field<string>("Class")
                             };
                List<GroupByModel> pDistinctDataRowsLinqToLst = result.ToList<GroupByModel>();
                #endregion
                #endregion

                #region 按列(vTableColumnName)分组  
                IEnumerable<IGrouping<string, GroupByModel>> pGroupByModelLst = pDistinctDataRowsLamdaToLst.Distinct().GroupBy<GroupByModel, string>(p => p.Name);
                
                foreach (IGrouping<string, GroupByModel> pModelLst in pGroupByModelLst)
                {
                    GroupByModel pIGroupByModel = new GroupByModel();
                    pIGroupByModel.Name = pModelLst.Key;

                    string pColumn2Value = string.Empty;

                    #region 相同Key值Value叠加方式一
                    pColumn2Value = pModelLst.Aggregate("", (a, b) =>
                    {
                        if (!string.IsNullOrEmpty(b.Class))
                        {
                            if (a == "")
                            {
                                return b.Class;
                            }
                            a += "," + b.Class;
                            return a;
                        }
                        else
                        {
                            return a;
                        }
                    });
                    #endregion

                    #region 相同Key值Value叠加方式2
                    //foreach (GroupByModel pGroupByModelItem in pModelLst)
                    //{
                    //    if (string.IsNullOrEmpty(pColumn2Value))
                    //    {
                    //        pColumn2Value = pGroupByModelItem.Class == null ? "" : pGroupByModelItem.Class.ToString();
                    //    }
                    //    else
                    //    {
                    //        pColumn2Value += pGroupByModelItem.Class == null ? "" : "," + pGroupByModelItem.Class.ToString();
                    //    }
                    //}
                    #endregion

                    pIGroupByModel.Class = pColumn2Value;

                    pIGroupByModelLst.Add(pIGroupByModel);
                }
                #endregion

                #region 统计数量
                object pObj = vDataTable?.AsEnumerable().Select(r => r[vTableColumnClass].ToString()).Distinct().Count();
                oDistinctCount = Convert.ToInt32(pObj);
                #endregion

                return pIGroupByModelLst;
            }
            catch (Exception ex)
            {
                CommonBasic.Log.BlossLog.AddErrorLog(ex);
                return null;
            }
        }
        #endregion
        #endregion

        #region 对外接口方法
        public static DataTable GetIGroupByModelTable(out int oDistinctCount)
        {
            oDistinctCount = 0;

            try
            {
                string pName = "Name";
                string pClassName = "Class";
                DataTable pDataTable = CreateCustomDataTable(pName, pClassName);

                string pOtherName = "姓名";
                string pOtherClassName = "班级";
                DataTable pDataTableResult = GetMergeColumDataTable(pDataTable, pName, pClassName, pOtherName, pOtherClassName, out int ooDistinctCount);
                oDistinctCount = ooDistinctCount;
                return pDataTableResult;
            }
            catch (Exception ex)
            {
                CommonBasic.Log.BlossLog.AddErrorLog(ex);
                return null;
            }
        }

        public static List<GroupByModel> GetIGroupByModelLst(out int oDistinctCount)
        {
            oDistinctCount = 0;

            try
            {
                string pName = "Name";
                string pClassName = "Class";
                DataTable pDataTable = CreateCustomDataTable(pName, pClassName);

                List<GroupByModel> pGroupByModelLst = GetMergeColumDataTableToLst(pDataTable, pName, pClassName, out int ooDistinctCount);
                oDistinctCount = ooDistinctCount;
                return pGroupByModelLst;
            }
            catch (Exception ex)
            {
                CommonBasic.Log.BlossLog.AddErrorLog(ex);
                return null;
            }
        }
        #endregion
    }
  • ViewModel
	public class GroupByViewModel:INotifyPropertyChanged
    {
        #region 字段属性
        public DataTable _pDataTableLst { get; set; }

        public DataTable pDataTableLst {
            get
            {
                return _pDataTableLst;
            }

            set
            {
                if (_pDataTableLst != value)
                {
                    _pDataTableLst = value;

                    OnNotifyPropertyChanged("pDataTableLst");
                }
            }
        }

        public List<GroupByModel> _pGroupByModelLst { get; set; }

        public List<GroupByModel> pGroupByModelLst
        {
            get
            {
                return _pGroupByModelLst;
            }

            set
            {
                if (_pGroupByModelLst != value)
                {
                    _pGroupByModelLst = value;

                    OnNotifyPropertyChanged("pGroupByModelLst");
                }
            }
        }

        public Int32 _pDataTableCount { get; set; }

        public Int32 pDataTableCount
        {
            get
            {
                return _pDataTableCount;
            }

            set
            {
                if (_pDataTableCount != value)
                {
                    _pDataTableCount = value;

                    OnNotifyPropertyChanged("pDataTableCount");
                }
            }
        }
        #endregion

        public GroupByViewModel()
        {
            pDataTableLst = GroupByModel.GetIGroupByModelTable(out int oDistinctCount);
            pGroupByModelLst = GroupByModel.GetIGroupByModelLst(out int oDistinctCount2);
        }

        #region INotifyPropertyChanged接口方法
        public virtual event PropertyChangedEventHandler PropertyChanged;
        public virtual void OnNotifyPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion
    }
  • UI 后台代码
	/// <summary>
    /// IGroupByStyleView.xaml 的交互逻辑
    /// </summary>
    public partial class IGroupByStyleView : Window
    {
        public IGroupByStyleView()
        {
            InitializeComponent();
            this.DataContext = new GroupByViewModel();
        }
    }
  1. 参考
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fengzhilu000

送人玫瑰,手留余香!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值