Use SelectMany and GroupBy

The following ProjectEnrolment defines the user in the project and his type of registration in it:

public class ProjectEnrolment {
  public Project Project { get; set; }
  public User User { get; set; }
  public EnrolmentType EnrolmentType { get; set; }
}

      

For testing purposes, I need to create a list of ProjectEnrolments, where:
1. For each project there should be no more than one project;
2. The user cannot appear twice in the project.

I tried the following:

List<ProjectEnrolment> projectEnrolments = 
  projects.SelectMany(x => 
  users.SelectMany(y => 
  enrolmentTypes.Select(z => 
    new ProjectEnrolment {
      EnrolmentType = z,
      Project = x,
      User = y
    })))          
  .GroupBy(u => u.Project)          
  .Select(v => v.OrderBy(w => Guid.NewGuid()).FirstOrDefault())
  .ToList();  

      

But this gives me one ProjectEnrolment for each project that I don't need.

+3


source to share


2 answers


Though it is possible I would not do what you want in one command using SelectMany

other linq methods as well. This is pretty tricky logic and the final instruction won't be readable. How about this:

Random r = new Random();
IList<ProjectEnrolment> projectEnrolments = new List<ProjectEnrolment>();
foreach (Project project in projects)
{
    int firstUser = r.Next(users.Count);
    projectEnrolments.Add(new ProjectEnrolment {
        EnrolmentType = enrolmentTypes[r.Next(enrolmentTypes.Count)],
        Project = project,
        User = users[firstUser]
    });
    int secondUser;
    do {
        secondUser = r.Next(users.Count);
    } while (secondUser == firstUser);
    projectEnrolments.Add(new ProjectEnrolment {
        EnrolmentType = enrolmentTypes[r.Next(enrolmentTypes.Count)],
        Project = project,
        User = users[secondUser]
    });
}

      



Linq version

IList<ProjectEnrolment> projectEnrolments = projects.SelectMany(p => users.OrderBy(u => Guid.NewGuid()).Take(2).Select(u => new ProjectEnrolment {
    EnrolmentType = enrolmentTypes.OrderBy(t => Guid.NewGuid()).FirstOrDefault(),
    Project = p,
    User = u
})).ToList();

      

+1


source


You can also use this one.
Here, each user will be registered for each project with a random registration type:



 Random rnd = new Random();
 var res = users.SelectMany(u => projects.Select(p => new ProjectEnrolment() {EnrolmentType = enrollmentTypes[rnd.Next(0, 3)], User = u, Project = p}))
.GroupBy(i => i.Project);

      

0


source







All Articles