比较 2 个列表中某个对象的 属性
Compare a property of an object in 2 lists
我有以下(简化)class:
public class CareRate {
[Key]
public int Id { get; set; }
public string Description { get; set; }
public decimal DayRate { get; set; }
}
我想比较 CareRate
的两个列表,仅通过它们的 DayRate
;一个 CareRates
包含当前 DayRates
,另一个 CareRates
包含要更新的 DayRates
。不应考虑可能已更改的其他属性,如描述。
// Just a test method
public List<CareRate> FilterChangedCareRates(){
var currentCareRates = new List<CareRate>{
new CareRate { Id = 1, DayRate = 3,33, Description = "Some descr" },
new CareRate { Id = 2, DayRate = 4,44, Description = "Some other descr" }
};
var updatedCareRates = new List<CareRate>{
new CareRate { Id = 1, DayRate = 2,22 },
new CareRate {Id = 2, DayRate = 4,44 } // Unchanged
};
var actualUpdatedCareRates = new List<CareRate>();
foreach(var updatedCareRate in updatedCareRates) {
var currentCareRate = currentCareRates.Single(x => x.Id == updatedCareRate.Id);
if (updatedCareRate.DayRate != currentCareRate.DayRate) {
actualUpdatedCareRates.Add(updatedCareRate);
}
}
return actualUpdatedCareRates;
}
通过Dayrate
过滤改变的CareRate
对象的方式感觉有点曲折。我想我忽略了一些东西。获取上述内容还有哪些其他更好的选择?
我想,你可以使用这样的东西:
updatedCareRates.ForEach(x =>
{
if (currentCareRates.FirstOrDefault(y => y.Id == x.Id && y.DayRate != x.DayRate) != null)
actualUpdatedCareRates.Add(x);
});
或一行:
updatedCareRates.Where(x => currentCareRates.FirstOrDefault(y => y.Id == x.Id &&
y.DayRate != x.DayRate) != null).ToList()
.ForEach(x => actualUpdatedCareRates.Add(x));
只需在 LINQ 中使用 Zip
方法:
var actualUpdatedCareRates = currentCareRates.Zip(updatedCareRates,
(f, s) => f.DayRate != s.DayRate ? s : null)
.Where(c => c != null).ToList();
你可以使用这个:
return (from up in updatedCareRates
join cur in currentCareRates
on up.Id equals cur.Id
where up.DayRate != cur.DayRate
select up).ToList();
这是我认为查询语法优于方法语法的罕见情况之一。
我没有使用 Where(x => x...)
,而是使用 Except
方法寻找解决方案 here。
我创建了一个 class DayRateComparer
,如下所示。
public class DayRateComparer : IEqualityComparer<CareRate>
{
public bool Equals(CareRate x, CareRate y) {
if (x = null) throw new ArgumentNullException(nameof(x));
if (y = null) throw new ArgumentNullException(nameof(y));
return x.Id == y.Id && x.DayRate == y.DayRate;
}
public int GetHashCode(CareRate obj) {
retun obj.Id.GetHashCode() + obj.DayRate.GetHashCode();
}
}
我这样使用 DayRateComparer
:
// Just a test method
public List<CareRate> FilterChangedCareRates(){
var currentCareRates = new List<CareRate>{
new CareRate { Id = 1, DayRate = 3,33, Description = "Some descr" },
new CareRate { Id = 2, DayRate = 4,44, Description = "Some other descr" }
};
var updatedCareRates = new List<CareRate>{
new CareRate { Id = 1, DayRate = 2,22 },
new CareRate {Id = 2, DayRate = 4,44 } // Unchanged
};
return updatedCareRates.Except(currentCareRates, new DayRateComparer()).ToList();
}
我不喜欢使用临时列表(如 actualUpdatedCareRates
),使用比较器时不再需要这样做。 提到的 Zip
方法也是一种干净而简短的方法,但乍一看对我来说有点复杂。谢谢大家的帖子。
我有以下(简化)class:
public class CareRate {
[Key]
public int Id { get; set; }
public string Description { get; set; }
public decimal DayRate { get; set; }
}
我想比较 CareRate
的两个列表,仅通过它们的 DayRate
;一个 CareRates
包含当前 DayRates
,另一个 CareRates
包含要更新的 DayRates
。不应考虑可能已更改的其他属性,如描述。
// Just a test method
public List<CareRate> FilterChangedCareRates(){
var currentCareRates = new List<CareRate>{
new CareRate { Id = 1, DayRate = 3,33, Description = "Some descr" },
new CareRate { Id = 2, DayRate = 4,44, Description = "Some other descr" }
};
var updatedCareRates = new List<CareRate>{
new CareRate { Id = 1, DayRate = 2,22 },
new CareRate {Id = 2, DayRate = 4,44 } // Unchanged
};
var actualUpdatedCareRates = new List<CareRate>();
foreach(var updatedCareRate in updatedCareRates) {
var currentCareRate = currentCareRates.Single(x => x.Id == updatedCareRate.Id);
if (updatedCareRate.DayRate != currentCareRate.DayRate) {
actualUpdatedCareRates.Add(updatedCareRate);
}
}
return actualUpdatedCareRates;
}
通过Dayrate
过滤改变的CareRate
对象的方式感觉有点曲折。我想我忽略了一些东西。获取上述内容还有哪些其他更好的选择?
我想,你可以使用这样的东西:
updatedCareRates.ForEach(x =>
{
if (currentCareRates.FirstOrDefault(y => y.Id == x.Id && y.DayRate != x.DayRate) != null)
actualUpdatedCareRates.Add(x);
});
或一行:
updatedCareRates.Where(x => currentCareRates.FirstOrDefault(y => y.Id == x.Id &&
y.DayRate != x.DayRate) != null).ToList()
.ForEach(x => actualUpdatedCareRates.Add(x));
只需在 LINQ 中使用 Zip
方法:
var actualUpdatedCareRates = currentCareRates.Zip(updatedCareRates,
(f, s) => f.DayRate != s.DayRate ? s : null)
.Where(c => c != null).ToList();
你可以使用这个:
return (from up in updatedCareRates
join cur in currentCareRates
on up.Id equals cur.Id
where up.DayRate != cur.DayRate
select up).ToList();
这是我认为查询语法优于方法语法的罕见情况之一。
我没有使用 Where(x => x...)
,而是使用 Except
方法寻找解决方案 here。
我创建了一个 class DayRateComparer
,如下所示。
public class DayRateComparer : IEqualityComparer<CareRate>
{
public bool Equals(CareRate x, CareRate y) {
if (x = null) throw new ArgumentNullException(nameof(x));
if (y = null) throw new ArgumentNullException(nameof(y));
return x.Id == y.Id && x.DayRate == y.DayRate;
}
public int GetHashCode(CareRate obj) {
retun obj.Id.GetHashCode() + obj.DayRate.GetHashCode();
}
}
我这样使用 DayRateComparer
:
// Just a test method
public List<CareRate> FilterChangedCareRates(){
var currentCareRates = new List<CareRate>{
new CareRate { Id = 1, DayRate = 3,33, Description = "Some descr" },
new CareRate { Id = 2, DayRate = 4,44, Description = "Some other descr" }
};
var updatedCareRates = new List<CareRate>{
new CareRate { Id = 1, DayRate = 2,22 },
new CareRate {Id = 2, DayRate = 4,44 } // Unchanged
};
return updatedCareRates.Except(currentCareRates, new DayRateComparer()).ToList();
}
我不喜欢使用临时列表(如 actualUpdatedCareRates
),使用比较器时不再需要这样做。 Zip
方法也是一种干净而简短的方法,但乍一看对我来说有点复杂。谢谢大家的帖子。