如何解决使用LINQ比较2个对象列表以获取更新的属性
我有2个相同类型的对象Student
列表:
public class Student {
public string StudentId { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string PostCode { get; set; }
}
我有2个StudentData
对象列表-去年列表和今年列表。我想查找学生姓名,地址或邮政编码已更改的数据。但是,我正在努力使用正确的LINQ查询。到目前为止,这是我尝试过的:
public DataChange<StudentData>[] Compare(StudentData[] previous,StudentData[] current) {
Guard.AgainstNull(previous,nameof(previous));
Guard.AgainstNull(current,nameof(current));
var updatedName = previous
.Where(d => current.Select(d2 => d2.StudentId )
.Contains(d.StudentId )).Where(d => !current.Select(d2 => d2.Name)
.Contains(d.Name)).Where(d => current.Select(d2 => d2.Address)
.Contains(d.Address)).Select(DataChange<StudentData>.Updated).ToList();
var updatedAddress = previous.Where(d => current
.Select(d2 => d2.StudentId )
.Contains(d.StudentId ))
.Where(d => !current.Select(d2 => d2.Address)
.Contains(d.Address))
.Where(d => current.Select(d2 => d2.Name)
.Contains(d.Name)).Select(DataChange<StudentData>.Updated).ToList();
var updatedNameAndAddress = previous
.Where(d => current.Select(d2 => d2.StudentId )
.Contains(d.StudentId )).Where(d => !current.Select(d2 => d2.Address)
.Contains(d.Address)).Where(d => !current.Select(d2 => d2.Name).Contains(d.Name))
.Select(DataChange<StudentData>.Updated).ToList();
}
我这样做的原因是为了满足这些情况:
- 名称已更新但地址未更新
- 地址已更新但名称未更新
但是,这不能通过测试案例,即学生的姓名已从“ Fred Blogs”更新为“ Fred Blogger”,或将地址从“ 123 Address”更新为“ 123 Updated”。
有人可以指出正确的方向,以获取正确的LINQ查询/更流畅的方法吗?
解决方法
这样的事情怎么了?
public DataChange<StudentData>[] Compare(StudentData[] previous,StudentData[] current) {
Guard.AgainstNull(previous,nameof(previous));
Guard.AgainstNull(current,nameof(current));
var updated = previous.Where(x => {
var newOne = current.FirstOrDefault(n => n.StudentId == x.StudentId);
if (newOne == null) {
return true; // this is considered a change,not found in 'current',but practically it is a 'delete'
}
return x.Address != newOne.Address || x.Name != newOne.Name;
}).Select(DataChange<StudentData>.Updated).ToList();
}
,
如果要查找姓名不同但地址不同的学生,则逻辑很简单:
- 在
StudentId
上找到匹配项 - 检查名称是否不同
- 检查地址是否相同
可以重复此操作,以使地址不同但名称不相同,并针对不同的名称和不同的地址。在代码中,它将类似于:
List<StudentData> updatedNames = previous.Where(prev => current.Any(cur =>
prev.StudentId == cur.StudentId && // Same student
prev.Name != cur.Name && // Different name
prev.Address == cur.Address)) // Same address
.ToList();
List<StudentData> updatedaddresses = previous.Where(prev => current.Any(cur =>
prev.StudentId == cur.StudentId && // Same student
prev.Name == cur.Name && // Same name
prev.Address != cur.Address)) // Different address
.ToList();
List<StudentData> updatedNameAndAddresses = previous.Where(prev => current.Any(cur =>
prev.StudentId == cur.StudentId && // Same student
prev.Name != cur.Name && // Different name
prev.Address != cur.Address)) // Different address
.ToList();
,
使用GroupJoin:
return current.GroupJoin(
previous,c => c.StudentId,p => p.StudentId,(c,ps) => {
if (ps?.Any() != true)
return DataChange<StudentData>.New();
// otherwise,ps should contain single value
// calculate the change in any appropriate way
return DataChange<StudentData>.FromOldAndNew(ps.First(),c);
}
)
// assuming null is returned for similar values
.Where(x => x is not null) // C# 9 feature,otherwise use !(x is null) or (x != null)
.ToArray();
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。