怎样才能获得一个列表?
你好,我有一个方法比较2个列表的差异对象。现在这个工作,但一次只有一个属性。怎样才能获得一个列表?
这里是方法:
public SPpowerPlantList compareTwoLists(string sqlServer, string database, DateTime timestampCurrent, string noteCurrent, DateTime timestampOld, string noteOld)
{
int count = 0;
SPpowerPlantList powerPlantListCurrent = loadProjectsAndComponentsFromSqlServer(sqlServer, database, timestampCurrent, noteCurrent);
SPpowerPlantList powerPlantListOld = loadProjectsAndComponentsFromSqlServer(sqlServer, database, timestampOld, noteOld);
SPpowerPlantList powerPlantListDifferences = new SPpowerPlantList();
count = powerPlantListOld.Count - powerPlantListCurrent.Count;
var differentObjects = powerPlantListCurrent.Where(p => !powerPlantListOld.Any(l => p.mwWeb == l.mwWeb)).ToList();
foreach (var differentObject in differentObjects)
{
powerPlantListDifferences.Add(differentObject);
}
return powerPlantListDifferences;
}
这工作,我也得到在新的清单4级的对象。问题是我有一些其他属性需要比较。例如名称而不是mwWeb。当我尝试更改它时,我需要为每个新属性添加一个新列表和一个新的Foreach循环。
例如
int count = 0;
SPpowerPlantList powerPlantListCurrent = loadProjectsAndComponentsFromSqlServer(sqlServer, database, timestampCurrent, noteCurrent);
SPpowerPlantList powerPlantListOld = loadProjectsAndComponentsFromSqlServer(sqlServer, database, timestampOld, noteOld);
SPpowerPlantList powerPlantListDifferences = new SPpowerPlantList();
SPpowerPlantList powerPlantListDifferences2 = new SPpowerPlantList();
count = powerPlantListOld.Count - powerPlantListCurrent.Count;
var differentObjects = powerPlantListCurrent.Where(p => !powerPlantListOld.Any(l => p.mwWeb == l.mwWeb)).ToList();
var differentObjects2 = powerPlantListCurrent.Where(p => !powerPlantListOld.Any(l => p.shortName == l.shortName)).ToList();
foreach (var differentObject in differentObjects)
{
powerPlantListDifferences.Add(differentObject);
}
foreach (var differentObject in differentObjects2)
{
powerPlantListDifferences2.Add(differentObject);
}
return powerPlantListDifferences;
有没有办法来防止这种情况?或者制作更多的查询并且只返回1个包含所有不同对象的列表?
我试过except
和intersect
但没有奏效。 因此,任何帮助或建议将是伟大的,thx为您的时间。
PS:如果我的问题风格有问题,请对我说,因为我试图学会提出更好的问题。
您可以简单地连锁,你想用你Where()
子句中进行比较的属性或声明:
// This should get you any elements that have different A properties, B properties, etc.
var different = current.Where(p => !old.Any(l => p.A == l.A || p.B == l.B))
.ToList();
如果这不起作用,并且您确实想使用Except()
或Intersect()
方法正确比较对象,你可以写自己的自定义IEqualityComparer<YourPowerPlant>
使用正确比较它们:
class PowerPlantComparer : IEqualityComparer<YourPowerPlant>
{
// Powerplants are are equal if specific properties are equal.
public bool Equals(YourPowerPlant x, YourPowerPlant 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;
// Checks the other properties to compare (examples using mwWeb and shortName)
return x.mwWeb == y.mwWeb && x.shortName == y.shortName;
}
// If Equals() returns true for a pair of objects
// then GetHashCode() must return the same value for these objects.
public int GetHashCode(YourPowerPlant powerPlant)
{
// Check whether the object is null
if (Object.ReferenceEquals(powerPlant, null)) return 0;
// Get hash code for the mwWeb field if it is not null.
int hashA = powerPlant.mwWeb == null ? 0 : powerPlant.mwWeb.GetHashCode();
// Get hash code for the shortName field if it is not null.
int hashB = powerPlant.shortName == null ? 0 : powerPlant.shortName.GetHashCode();
// Calculate the hash code for the product.
return hashA^hashB;
}
}
,然后你可能会使用像下面这样的一个根据您的需要:
var different = current.Except(old,new PowerPlantComparer());
或:
var different = current.Intersect(old,new PowerPlantComparer());
Thx这与clas很好地工作。 – opelhatza
要做到这一点是比较一些独特的标识符,最简单的方法(ID)
var differentObjects = powerPlantListCurrent
.Where(p => !powerPlantListOld.Any(l => p.Id == l.Id)
.ToList();
如果其他属性可能已更新,并要检查过,你就必须比较所有他们检测到现有的元素进行修改:
实现一个camparison法(IComparable
,IEquatable
,IEqualityComparer
,或覆盖Equals
),或者,如果是因为你不是你自己写的类(生成的或外部的代码是不可能的组装),编写一个方法来比较两个o f那些SPpowerPlantList
元素并使用它来代替比较Linq中的每个属性。例如:
public bool AreThoseTheSame(SPpowerPlantList a,SPpowerPlantList b)
{
if(a.mwWeb != b.mwWeb) return false;
if(a.shortName != b.shortName) return false;
//etc.
return true;
}
然后用此取代你的区别来电:
var differentObjects = powerPlantListCurrent
.Where(p => !powerPlantListOld.Any(l => AreThoseTheSame(p,l))
.ToList();
使用IEqualityComparer更简单,更美观。 :-) –
@ Sebastian-Schulz同意,这就是为什么我提到它作为首选选项:),编辑:哦,等等 - 这是我忘记的界面 –
记住,当你重写'Equals'时,你必须重写'GetHashCode'! – derpirscher
作为Rion Williams的建议,一种方法是使用IEqualityComparer
,如果您想要更灵活的解决方案,可以将逻辑分为两部分。首先创建接受两个列表的帮助器方法,并在其中定义您希望比较的属性。例如:
public static class Helper
{
public static SPpowerPlantList GetDifference(this SPpowerPlantList current, SPpowerPlantList old, Func<PowerPlant, PowerPlant, bool> func)
{
var diff = current.Where(p => old.All(l => func(p, l))).ToList();
var result = new SPpowerPlantList();
foreach (var item in diff) result.Add(item);
return result;
}
}
并使用它:
public SPpowerPlantList compareTwoLists(string sqlServer, string database,
DateTime timestampCurrent, string noteCurrent,
DateTime timestampOld, string noteOld)
{
var powerPlantListCurrent = ...;
var powerPlantListOld = ...;
var diff = powerPlantListCurrent.GetDifference(
powerPlantListOld,
(x, y) => x.mwWeb != y.mwWeb ||
x.shortName != y.shortName);
return diff;
}
附:如果能更好地满足您的需求,您可以在现有类的内部移动方法:
public class MyClass
{
public SPpowerPlantList GetDifference(SPpowerPlantList current, SPpowerPlantList old, Func<PowerPlant, PowerPlant, bool> func)
{
...
}
}
,并呼吁它(内部类):
var result = GetDifference(currentValues, oldValues, (x, y) => x.mwWeb != y.mwWeb);
我认为你需要实现的IEqualityComparer为对象。然后'除了'和'交叉'将起作用。 https://blogs.msdn.microsoft.com/mcsuksoldev/2011/04/05/linq-distinct-and-iequalitycomparer-implementation/ –
为什么不重写'Equals()'和'GetHashCode()'? – derpirscher