Search code examples
c#linq

Linq: Edit GroupID of Students based on Common Interests


I have a list of students with their subject of interests (separated by comma).

List<Students> students = new List<Students>(); 
                           
students.Add(new Students() { Name = "Krishna", GroupID= 0, Interests = "Physics,Maths" });

students.Add(new Students() { Name = "Ganesh", GroupID= 0, Interests = "History,Physics" });

students.Add(new Students() { Name = "Jayesh", GroupID= 0, Interests = "Tech,Humanity" });

students.Add(new Students() { Name = "Aditya", GroupID= 0, Interests = "Science"});

students.Add(new Students() { Name = "Ramesh", GroupID= 0, Interests = "Programming,Science"});

I want to use the Linq to edit the GroupID of students in the same list based on their common interests.

Expected Output:

GroupID 1; Students: Krishna, Ganesh (Reason: Common interest in Physics)

GroupID 2; Students: Aditya, Ramesh (Reason: Common interest in Science)

Any help is greatly appreciated.

Thank you so much!


Solution

  • So first thing I did to solve this was create a dictionary of values to correspond to the interest. You can of course hard code these if you want, but I made them based on order they were found. I then processed your list and expanded it to group by the key value from dictionary and then reprocessed your students list to assign the group ids. I split things into methods for you to better see. Please view below. I think you will want to reconsider how you are grouping interest though. This will only work with 2 interest and if anyone overlaps you have no way to handle that with your current class. I think you might want to revisit your model first.

    What I mean is what happens if say Krishna also had Tech as an interest. The code would overlap and give her a 3, and Ganesh a 1 still thus removing from group.

    Before:

    enter image description here

    After:

    enter image description here

    void Main()
    {
        List<Students> students = new List<Students>();
    
        students.Add(new Students() { Name = "Krishna", GroupID = 0, Interests = "Physics,Maths" });
    
        students.Add(new Students() { Name = "Ganesh", GroupID = 0, Interests = "History,Physics" });
    
        students.Add(new Students() { Name = "Jayesh", GroupID = 0, Interests = "Tech,Humanity" });
    
        students.Add(new Students() { Name = "Aditya", GroupID = 0, Interests = "Science" });
    
        students.Add(new Students() { Name = "Ramesh", GroupID = 0, Interests = "Programming,Science" });
        
        //students.Dump();
        
        CreateInterestDictionary(students);
        
        var studentsExpanded = ExpandStudents(students);
        
        var studentsGrouped = studentsExpanded.GroupBy(x => x.GroupID).Where(x => x.Count() > 1).ToList();
        studentsGrouped.ForEach(x =>
        {
            x.ToList().ForEach(y => {
                var student = students.Where(z => z.Name == y.Name).FirstOrDefault();
                student.GroupID = x.Key;
            });
        });
        
        //students.Dump();
    }
    
    
    public static Dictionary<string, int> InterestDict = new Dictionary<string, int>();
    // You can define other methods, fields, classes and namespaces here
    public class Students
    {
        public string Name {get; set;}
        public int GroupID {get; set;}
        public string Interests {get; set;}
    }
    
    public static List<Students> ExpandStudents(List<Students> students)
    {
        List<Students> studentsExpanded = new List<Students>();
    
        students.ForEach(x =>
        {
            if (x.Interests.Contains(","))
            {
                var interestSplit = x.Interests.Split(',');
                interestSplit.ToList().ForEach(y =>
                {
                    studentsExpanded.Add(new Students() { Name = x.Name, GroupID = InterestDict[y], Interests = y });
                });
            }
            else
            {
                studentsExpanded.Add(new Students() { Name = x.Name, GroupID = InterestDict[x.Interests], Interests = x.Interests });
            }
        });
        
        return studentsExpanded;
    }
    
    public static Dictionary<string, int> CreateInterestDictionary(List<Students> students)
    {
        var count = 1;
        students.ForEach(x =>
        {
            if (x.Interests.Contains(","))
            {
                var interestSplit = x.Interests.Split(',');
                interestSplit.ToList().ForEach(y =>
                {
                    if (!InterestDict.ContainsKey(y))
                    {
                        InterestDict.Add(y, count);
                        count += 1;
                    }
    
                });
    
            }
            else
            {
                if (!InterestDict.ContainsKey(x.Interests))
                {
                    InterestDict.Add(x.Interests, count);
                    count += 1;
                }
            }
        });
        
        return InterestDict;
    }
    

    A potential issue though is your classes aren't really setup to handle if a student has an interest with more than 1 other student. For example:

    what happens if say Krishna also had Tech as an interest. The code would overlap and give her a 3, and Ganesh a 1 still thus removing from group.

    enter image description here