I have two lists of objects, let's suppose that the first is called Department and the second is called Student.
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; }
}
Remarks: The list of users is filled with many objects ( more than 150 000 items ).
For that reason, I've used 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;
});
}
I would like to compare two lists of users and departments and get the results between them and then set the attribute IsActive
to false .
Example :
List students: {1,"John",True,001} , {2,"Mariah",True,003},{3,"Karima",True,002},{4,"Jenny",True,004}
List departments: {001,"Science"} , {002,"Culture"}
The expected result:
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}
What can I do to make the above code works?
CodePudding user response:
I think you want to increase performace. For that you can use Parallel.For instead of foreach loop since you have lot of objects.
Parallel.ForEach(students, s =>
{
if (results.ToList().Exists(p => p.DepId== s.DepId))
{
s.IsActive = false;
}
});
It is available in System.Threading.Tasks;
CodePudding user response:
try this
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;
});
}
output
1 John True 1
2 Mariah False 3
3 Karima True 2
4 Jenny False 4
or if you for some reason are expecting on the contrary you can use this, and it is using TPL library too
await Task.Run(() =>
{
Parallel.ForEach(students, s =>
{
if (departments.Exists(p => p.DepId == s.DepId))
{
s.IsActive= false;
}else s.IsActive=true;
});
output
1 John False 1
2 Mariah True 3
3 Karima False 2
4 Jenny True 4
but IMHO the fastest way would be if you make a left join students and departments in data base server already
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;
});
in this case you need to add one more property to student
[NotMapped]
public bool DepExist { get; set; }
CodePudding user response:
Store the department ids in a HashSet<int>
:
var hashSet = new HashSet<int>(departments.Select(x => x.DepId));
...and iterate through the students:
var results = new List<Student>();
foreach (var student in students)
{
if (hashSet.Contains(student.DepId)
{
results.Add(student);
student.IsActive = false;
}
}
Since you only have one Student
object per student, the IsActive
property cannot be true
on one collection and false
in another. If you want two different objects, you should clone the original one.