我如何比较2个列表并且具有不匹配的项目,但是根据具体属性
public partial class Cable : StateObject
{
public int Id { get; set; }
public int CablePropertyId { get; set; }
public int Item { get; set; }
public int TagNo { get; set; }
public string GeneralFormat { get; set; }
public string EndString { get; set; }
public string CableRevision { get; set; }
}
我想比较完成对CablePropertyId,TagNo和CableRevision的比较,如果我使用
var diffCables = sourceCables.Except(destinationCables).ToList();
将整个属性相互比较。我怎么能这样做?
答案 0 :(得分:4)
使用Linq除了使用自定义EqualityComparer的方法。
http://msdn.microsoft.com/en-us/library/bb336390(v=vs.110).aspx
class CableComparer : IEqualityComparer<Cable>
{
public bool Equals(Cable x, Cable y)
{
return (x.CablePropertyId == y.CablePropertyId && ...);
}
public int GetHashCode(Cable x) // If you won't create a valid GetHashCode based on values you compare on, Linq won't work properly
{
unchecked
{
int hash = 17;
hash = hash * 23 + x.CablePropertyID;
hash = hash * 23 + ...
}
return hash;
}
}
var diffCables = sourceCables.Except(destinationCables, new CableComparer());
此外,对结果的ToList()
操作并不是必需的。大多数情况下,您只需操作Linq查询IEnumerable
的结果,而无需指定确切的类型;这样,您就不会在不需要的ToList()
操作上浪费性能。
顺便说一下,其他几个人提出了简单lambda的基于位置的查询。这种解决方案更容易阅读(在我看来),但它也不太优化:它强制n ^ 2检查,而IEqualityComparer允许Linq因GetHashCode()
方法更优化。这是一个great answer on importance of GetHashCode,这里是great guide on writing GetHashCode()
override。
答案 1 :(得分:1)
您可以像这样创建自己的IEqualityComparer<Cable>
:
public class CableComparer : IEqualityComparer<Cable>
{
public bool Equals(Cable x, Cable y)
{
return x.CablePropertyId == y.CablePropertyId &&
x.TagNo == y.TagNo &&
x.CableRevision == y.CableRevision;
}
// If Equals() returns true for a pair of objects
// then GetHashCode() must return the same value for these objects.
public int GetHashCode(Cable x)
{
return x.CablePropertyId ^
x.TagNo.GetHashCode() ^
x.CableRevision.GetHashCode();
}
}
var comparer = new CableComparer();
var diffCables = sourceCables.Except(destinationCables, comparer).ToList();
或者,MoreLINQ library(也available on NuGet)提供了一种方便的ExceptBy
方法:
var diffCables = sourceCables.ExceptBy(
destinationCables,
x => new {
x.CablePropertyId,
x.TagNo,
x.CableRevision
})
.ToList();
答案 2 :(得分:0)
答案 3 :(得分:0)
如果将LINQ与IQueryable<>
一起使用,则可能存在Where()
var destinationCablesAnon = destinationCables.Select(a=>new {a.CablePropertyId, a.TagNo ,a.CableRevision}); // add ToArray() if use IEnumerable<>
var diffCables = sourceCables.Where(a=>!destinationCables.Contains(new {a.CablePropertyId, a.TagNo ,a.CableRevision})).ToList();
答案 4 :(得分:0)
基本上,当您想要比较自己的类型时,您需要描述它们之间的比较/区别。 Linq不知道你Cable
班的哪些属性不同?
因此,您构建了一个比较器,通常可用于比较两种类型。
在这种情况下,有两个Cable
个实例:
class CableComparer : IEqualityComparer<Cable>
{
public bool Equals(Cable c1, Cable c2)//these represent any two cables.
{
if (c1.Height == c2.Height && ...)
{
return true;
}
else
{
return false;
}
}
public int GetHashCode(Cable c)
{
//this will work if each ID is unique
return c.Id.GetHashCode();
//otherwise you do this:
//return (c.Id ^ c. CablePropertyId).GetHashCode();
}
}
然后:
IEnumerable<Cable> except =
sourceCables.Except(destinationCables, new CableComparer());
答案 5 :(得分:0)
我认为你可以使用这样的东西:
sourceCables.Where(sc => !destinationCables.Any(dc => dc.CablePropertyId == sc.CablePropertyId && ...));