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!
CodePudding user response:
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:
After:
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.