Home > Enterprise >  Get the result of two compared list and change an attribut in list deponding on the result using LIN
Get the result of two compared list and change an attribut in list deponding on the result using LIN

Time:10-08

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.

  • Related