当前位置 : 主页 > 网络编程 > c#编程 >

Linq利用Distinct去除重复项问题(可自己指定)

来源:互联网 收集:自由互联 发布时间:2023-03-22
目录 Linq利用Distinct去除重复项 Linq利用Except去除重复数据并返回唯一数据(IEqualityComparer扩展) 效果图 总结 Linq利用Distinct去除重复项 添加一个扩展方法 public static IEnumerableTSource DistinctB
目录
  • Linq利用Distinct去除重复项
  • Linq利用Except去除重复数据并返回唯一数据(IEqualityComparer扩展)
    • 效果图
  • 总结

    Linq利用Distinct去除重复项

    添加一个扩展方法

    public static IEnumerable<TSource> DistinctBy<TSource, TKey> (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
    {
        HashSet<TKey> seenKeys = new HashSet<TKey>();
        foreach (TSource element in source)
        {
            if (seenKeys.Add(keySelector(element)))
            {
                yield return element;
            }
        }
    }

    使用方法如下(针对ID,和Name进行Distinct)

    var query = people.DistinctBy(p => new { p.Id, p.Name });

    若仅仅针对ID进行distinct:

    var query = people.DistinctBy(p => p.Id);

    Linq利用Except去除重复数据并返回唯一数据(IEqualityComparer扩展)

    前段时间做一个项目就是定时下载节目列表进行对文件时间和名字进行新旧对比进行去重复,众所周知,我们在Linq中去重复数据都用Distinct()做。

    但如果想多个条件进行对比去除重复数据,我们应该怎么办呢?

    请看下文,利用Except (通过使用默认的相等比较器对值进行比较,生成两个序列的差集。)

      //
            // 摘要:
            //     通过使用默认的相等比较器对值进行比较,生成两个序列的差集。
            //
            // 参数:
            //   first:
            //     System.Collections.Generic.IEnumerable`1 也不是在其元素 second 将返回。
            //
            //   second:
            //     System.Collections.Generic.IEnumerable`1 同时出现在第一个序列的元素将导致从返回的序列中移除这些元素。
            //
            // 类型参数:
            //   TSource:
            //     输入序列中的元素的类型。
            //
            // 返回结果:
            //     包含这两个序列的元素的差集的序列。
            //
            // 异常:
            //   T:System.ArgumentNullException:
            //     first 或 second 为 null。
            public static IEnumerable<TSource> Except<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second);

    示例:

    public class ChannelTvListInfo
        {
            public string TVName { get; set; } //节目列表名字
            public string LastWriteTime { get; set; }//最后编辑文件时间
        }
    private List<ChannelTvListInfo> lstNewTvInfo, lstOldTvInfo = new List<ChannelTvListInfo>();
    		private void button3_Click(object sender, EventArgs e)
    		{       //通过下载后与定时下载的目录文件进行名字及最后编辑文件的时间进行对比更新
    			lstNewTvInfo = listFTPFiles("60.208.140.xxx", "", "");
    			DirectoryInfo TheFolder = new DirectoryInfo(@"D:\ChannelTvXML\");
    			foreach (FileInfo NextFile in TheFolder.GetFileSystemInfos())
    			{
    				lstOldTvInfo.Add(new ChannelTvListInfo { TVName = NextFile.Name, LastWriteTime = 
    NextFile.LastWriteTime.ToString("yyyy/MM/dd hh:mm tt") });
    			}
    			
    		}
    		public List<ChannelTvListInfo> listFTPFiles(string FTPAddress, string username, string password)
    		{
    			List<ChannelTvListInfo> listinfo = new List<ChannelTvListInfo>();
    			using (FtpConnection ftp = new FtpConnection(FTPAddress, username, password))
    			{
    				ftp.Open();
    				ftp.Login();
    				foreach (var file in ftp.GetFiles("/"))
    				{
    					listinfo.Add(new ChannelTvListInfo
    					{
    						TVName = file.Name,
    						LastWriteTime = Convert.ToDateTime(file.LastWriteTime).ToString("yyyy/MM/dd hh:mm tt")
    					});
    				}
    				ftp.Dispose();
    				ftp.Close();
    			}
    			return listinfo;
    		}

    效果图

    1:自动从FTP目录下载下来的xml 节目列表:

    2:从上一个时间段自动下来的存放的目录获取文件列表

    或者新旧List列表中的 差异节目列表方法:

    var result = lstNewTvInfo.Except(lstOldTvInfo.Where(x=>x.TVName.Contains("四川")), new ProductComparer()).ToList();

    以下示例显示如何实现可在Distinct <TSource>方法中使用的等式比较器。

    	public class ProductComparer : IEqualityComparer<ChannelTvListInfo>
    	{
    		// Products are equal if their names and product numbers are equal.
    		public bool Equals(ChannelTvListInfo x, ChannelTvListInfo y)
    		{
     
    			//Check whether the compared objects reference the same data.
    			if (Object.ReferenceEquals(x, y)) return true;
     
    			//Check whether any of the compared objects is null.
    			if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
    				return false;
     
    			//Check whether the products' properties are equal.
    			return x.TVName == y.TVName && x.LastWriteTime == y.LastWriteTime;
    		}
     
    		// If Equals() returns true for a pair of objects 
    		// then GetHashCode() must return the same value for these objects.
     
    		public int GetHashCode(ChannelTvListInfo product)
    		{
    			//Check whether the object is null
    			if (Object.ReferenceEquals(product, null)) return 0;
     
    			//Get hash code for the Name field if it is not null.
    			int hashProductName = product.TVName == null ? 0 : product.TVName.GetHashCode();
     
    			//Get hash code for the Code field.
    			int hashProductCode = product.LastWriteTime.GetHashCode();
     
    			//Calculate the hash code for the product.
    			return hashProductName ^ hashProductCode;
    		}
     
    	}

    最终返回结果就是有差异的

    总结

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持自由互联。

    上一篇:C#中括号强转、as、is区别详解
    下一篇:没有了
    网友评论