使用 LINQ 获取两个比较列表的结果并根据结果更改列表中的属性
Posted
技术标签:
【中文标题】使用 LINQ 获取两个比较列表的结果并根据结果更改列表中的属性【英文标题】:Get the result of two compared list and change an attribut in list deponding on the result using LINQ 【发布时间】:2021-11-28 08:24:22 【问题描述】:我有两个对象列表,假设第一个称为部门,第二个称为学生。
public class Student
public int Id get; set;
public string Name get; set;
public bool IsActive get; set;
public int DepId get;set;
public class Department
public int DepId get; set;
public string DepName get; set;
备注:用户列表中包含许多对象(超过 150 000 项)。
因此,我使用了Task.Run()
private async Task UpdateMyGrid()
departments = ....; // list of departments
students = ..... ; // list of students
await Task.Run(() =>
var results = students.Where(x => departments.Any(y => y.DepId== x.DepId));
foreach (var s in students)
if (results.ToList().Exists(p => p.DepId== s.DepId))
s.IsEnabled = false;
GridViewStudent.ItemsSource = null;
GridViewStudent.ItemsSource = students;
);
我想比较两个用户和部门列表并得到它们之间的结果,然后将属性 IsActive
设置为 false 。
例子:
List students: 1,"John",True,001 , 2,"Mariah",True,003,3,"Karima",True,002,4,"Jenny",True,004
List departments: 001,"Science" , 002,"Culture"
预期结果:
Results will be => 1,"John",True,001,3,"Karima",True,002
Students will be => 1,"John",False,001 , 2,"Mariah",True,003,
3,"Karima",False,002,4,"Jenny",True,004
我该怎么做才能使上述代码正常工作?
【问题讨论】:
但是不使用它我的用户界面被屏蔽了 实际问题是什么?你有预期的输入/输出吗? 我举个例子。 立即查看更新。 我不明白逻辑 - 预期和实际之间的逻辑是什么?您是否尝试根据部门是否存在来修改学生活动状态?你想输出结果还是学生? 【参考方案1】:试试这个
private async Task UpdateMyGrid()
await Task.Run(() =>
foreach (var s in students)
if (departments.Exists(p => p.DepId == s.DepId))
s.IsActive= true;
else s.IsActive=false;
GridViewStudent.ItemsSource = null;
GridViewStudent.ItemsSource = students;
);
输出
1 John True 1
2 Mariah False 3
3 Karima True 2
4 Jenny False 4
或者如果你出于某种原因期望相反,你可以使用它,它也在使用 TPL 库
await Task.Run(() =>
Parallel.ForEach(students, s =>
if (departments.Exists(p => p.DepId == s.DepId))
s.IsActive= false;
else s.IsActive=true;
);
输出
1 John False 1
2 Mariah True 3
3 Karima False 2
4 Jenny True 4
但恕我直言,最快的方法是如果您已经在数据库服务器中左连接学生和部门
var students = await (from s in context.students
join d in context.departments on s.DepId equals d.DepId into gj
from d in gj.DefaultIfEmpty()
select new Student
Id=s.Id,
Name=s.Name,
DepId=s.DepId,
DepExist= d==null?false: true,
).ToListAsync();
Parallel.ForEach(students, s =>
s.IsActive = s.DepExist;
);
在这种情况下,您需要向学生添加一个属性
[NotMapped]
public bool DepExist get; set;
【讨论】:
OP 说预期的输出是1,"John",False,001 , 2,"Mariah",True,003, 3,"Karima",False,002,4,"Jenny",True,004
?
@ErmiyaEskandary 谢谢,我放了 2 个变体,因为它很混乱。我想如果一个部门存在,那么一个学生是活跃的
这里一样,不用担心 - 等待 OP
是的,学生名单取决于部门。我将搜索学生中的学生是否存在于部门列表中,isActive 将是False
@csharp_devloper31 很难用两个词来解释。您可以阅读本教程,例如 dotnettutorials.net/lesson/parallel-foreach-method-csharp【参考方案2】:
我认为您想提高性能。 为此,您可以使用 Parallel.For 而不是 foreach 循环,因为您有很多对象。
Parallel.ForEach(students, s =>
if (results.ToList().Exists(p => p.DepId== s.DepId))
s.IsActive = false;
);
在 System.Threading.Tasks 中可用;
【讨论】:
谢谢,但问题与性能无关,请再次阅读我的问题。【参考方案3】:将部门 ID 存储在 HashSet<int>
:
var hashSet = new HashSet<int>(departments.Select(x => x.DepId));
...并遍历学生:
var results = new List<Student>();
foreach (var student in students)
if (hashSet.Contains(student.DepId)
results.Add(student);
student.IsActive = false;
由于每个学生只有一个 Student
对象,因此 IsActive
属性不能在一个集合中为 true
而在另一个集合中为 false
。如果你想要两个不同的对象,你应该克隆原来的那个。
【讨论】:
以上是关于使用 LINQ 获取两个比较列表的结果并根据结果更改列表中的属性的主要内容,如果未能解决你的问题,请参考以下文章