当比较两个大的pocos列表时,从第一个列表中获取不匹配的项目



我有两个对象列表,它们有一个名为OrderNumber的公共属性。

第一份清单有大约20000项,第二份清单有150万项。

我需要一种有效的方法来从列表1中找到与列表2中不匹配的项目。我目前正在使用Linq,计算解决方案需要20多分钟。我在网上找不到有效的解决方案。

到目前为止我的代码

notmatched.AddRange(List1.Where(l1=> !list2.Select(l2=> l2.OrderNumber).Contains(l1.OrderNumber)).Select(l1 => new SomeObj 
{
OrderNumber = l1.OrderNumber
}));

使用Linq提供的内置Except扩展足够快,可以提供自定义的IEqualityComparer。我的实现可能不适用于您的用例,但考虑到firstList中有150万个Poco类,secondList中有20k个,它在1秒内执行。

IEqualityComparer,Linq的文档,除外

DotnetFiddle-减少数字以绕过内存限制

// Classes used in test: 
public interface IOrderNumber
{
string OrderNumber { get; set; }
}
public class Poco: IOrderNumber
{
public string OrderNumber { get; set; }
}
public class Podo: IOrderNumber
{
public string OrderNumber {get;set;}
}
public class DataEqualityComparer : IEqualityComparer<IOrderNumber>
{
public bool Equals(IOrderNumber p1, IOrderNumber p2)
{
var equal = GetHashCode(p1) == GetHashCode(p2);
return equal;
}
public int GetHashCode(IOrderNumber p1)
{
if (p1 == null)
return -1;
int hCode = p1.OrderNumber.GetHashCode();
return hCode.GetHashCode();
}
}

... then your code would look like this: 
var firstList = Enumerable.Range(1, 1500000).Select(x => new Poco { OrderNumber = x.ToString() }).ToList();
var secondList = Enumerable.Range(50, 20000).Select(x => new Podo { OrderNumber = x.ToString() }).ToList();
Stopwatch sw = Stopwatch.StartNew();
var result = firstList.Except(secondList, new DataEqualityComparer()).ToList();
sw.Stop();
Console.WriteLine($"Duration: {sw.Elapsed:G}");

这是您的解决方案的一个更简化的版本,它使用更少的循环来完成这项工作,但我不确定这是否会使过程更快,请告诉我它是否能完成

notmatched.AddRange(List1.Where(l1=> !list2.Any(l2=> l2.OrderNumber == l1.OrderNumber).Select(l1 => new SomeObj 
{
OrderNumber = l1.OrderNumber
}));

使用LinqExcept来比较对象。必须为复杂对象实现IEquatable接口。

using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
var first =  new  List<Poco> { new Poco {OrderNumber = "test", Orderid = 1 }, new Poco {OrderNumber = "test", Orderid = 1 }  };
var second =  new  List<Poco> { new Poco {OrderNumber = "test", Orderid = 1 }, new Poco {OrderNumber = "test", Orderid = 1 }  };
first.Except(second).Dump();
second.Except(first).Dump();
if ( !first.Except(second).Any() && !second.Except(first).Any())
{
Console.Write("first and second are equal");
} else {

Console.Write("equality failed");
}

}
}
public class Poco : IEquatable<Poco>
{
public string OrderNumber { get; set; }
public int Orderid {get; set;}
public  bool Equals(Poco other)
{
if (other == null )
return false;
return this.Orderid == other.Orderid &&  this.OrderNumber == other.OrderNumber;

}
public override bool Equals(Object obj)
{
if (obj == null)
return false;
Poco poco = obj as Poco;
if (poco == null)
return false;
else
return Equals(obj);
}

public override int GetHashCode() => (Orderid, OrderNumber).GetHashCode();

}

相关内容

  • 没有找到相关文章

最新更新