我有一个类似于以下信息的数据集。
我想做的是用尽可能多的可用信息填充一个对象。
所以我想从顶部数据集中获取 UnitNum 65002,其余的从单列表中获取。
我的代码:
foreach (DataRow row in dsUnits.Tables[0].Rows)
{
var unit = new Unit.Unit
{
UnitNum = row["UnitNumber"].NullSafeToString(),
CustCode = row["CustCode"].NullSafeToString(),
Year = row["Year"].NullSafeToString(),
Make = row["Make"].NullSafeToString(),
Model = row["Model"].NullSafeToString()
};
UnitsInvolvedInBreakdown.Add(unit);
}
foreach (DataRow row in dsUnits.Tables[1].Rows)
{
if (UnitsInvolvedInBreakdown.Where(x => x.UnitNum == row["UnitNumber"].ToString()).Count() == 0)
{
var unit = new Unit.Unit
{
UnitNum = row["UnitNumber"].ToString()
};
UnitsInvolvedInBreakdown.Add(unit);
}
}
这对我来说似乎效率很低,我尝试了下面的代码但没有结果,
var q = dsUnits.Tables[0].AsEnumerable().Except(dsUnits.Tables[1].AsEnumerable());
我的问题基本上是,是否有一种方法可以使用 linq 从表 0 中选择 UnitNumbers,前提是它们不存在于表 1 中
更好的解释。
单元号将在表 1 中。它可能在表 0 中。
如果它在表 0 中,我想从那里获取信息..我有更多信息。
如果它不在表 0 中,我想从表 1 中获取信息,因为我必须获取我能获取的信息。但我不想重复。
最佳答案
如果我了解您的要求,这就是您要找的。它首先从表一中获取所有内容,然后通过 Linq 左外连接获取所有不在表一中但在表二中的内容:
var unitsFrom1 = dsUnits.Tables[0].AsEnumerable()
.Select(row => new Unit.Unit
{
UnitNum = row["UnitNumber"].NullSafeToString(),
CustCode = row["CustCode"].NullSafeToString(),
Year = row["Year"].NullSafeToString(),
Make = row["Make"].NullSafeToString(),
Model = row["Model"].NullSafeToString()
});
var unitsFrom2Notin1 =
from row in dsUnits.Tables[1].AsEnumerable()
join u1 in unitsFrom1
on row.Field<string>("UnitNumber") equals u1.UnitNum into outer
from outerJoin in outer.DefaultIfEmpty()
where outerJoin == null
select new Unit.Unit
{
UnitNum = row["UnitNumber"].NullSafeToString()
};
现在你可以连接两者:
IEnumerable<Unit.Unit> result = unitsFrom1.Concat(unitsFrom2Notin1);
这是一种更易于维护且在任何情况下都应该有效的不同方法。您可以实现自定义 IEqualityComparer<Unit>
您可以将其用于许多(基于集合的)LINQ 方法,例如 Join
, Intersect
, Union
, GroupBy
.您也可以将它用于 HashSet<Unit.Unit>
在这种情况下我更喜欢。这是 UnitComparer
的可能实现:
public class UnitComparer : IEqualityComparer<Unit>
{
public bool Equals(Unit x, Unit y)
{
if (x == null && y == null) return true;
if (x == null || y == null) return false;
return x.UnitNum == y.UnitNum;
}
public int GetHashCode(Unit obj)
{
return obj == null || obj.UnitNum == null ? 0 : obj.UnitNum.GetHashCode();
}
}
这是您需要的简单循环,从第一个开始获取所有内容,从第二个获取所有不在第一个中的内容。注意 HashSet<T>
constructor我使用的:
var uniqueUnits = new HashSet<Unit.Unit>(new Unit.UnitComparer());
foreach (DataRow row in dsUnits.Tables[0].Rows)
{
Unit.Unit unit = new Unit.Unit
{
UnitNum = row["UnitNumber"].NullSafeToString(),
CustCode = row["CustCode"].NullSafeToString(),
Year = row["Year"].NullSafeToString(),
Make = row["Make"].NullSafeToString(),
Model = row["Model"].NullSafeToString()
};
uniqueUnits.Add(unit);
}
foreach (DataRow row in dsUnits.Tables[1].Rows)
{
Unit.Unit unit = new Unit.Unit
{
UnitNum = row["UnitNumber"].NullSafeToString()
};
uniqueUnits.Add(unit);
}
HashSet<T>.Add
返回 false
如果因为它已经在集合中而无法添加。
关于c# - 使用 LINQ 在两个表之间选择不同的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29034929/