Linq利用Distinct去除重复项问题(可自己指定)
作者:MrCui.
这篇文章主要介绍了Linq利用Distinct去除重复项问题(可自己指定),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
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; } }
最终返回结果就是有差异的
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。