3

私はこれらの3つのクラスを持っています:

  • 従業員
  • 学生

コード:

public class Employee
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    public string Gender { get; set; }
    public long TimeStamp { get; set; }
}
    
public class Student
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    public long TimeStamp { get; set; }
}
    
public class Person<br>
{
    public string Name { get; set; }
    public int Age { get; set; }
}

私は4つのリストを作成します:

var studentList = new List<Student>();// fill the List with a lot of Stundents
var employeeList = new List<Student>(); // fill the List with a lot of employees
var personList1 = new List<Person>();
var personList2 = new List<Person>();

すべての学生と従業員を選択

var allStudents = studentList.Select(a => a); // does not make a lot of sence but for testing 
var allEmployee = employeeList.Select(b => b);

allStudents をマップしたい

personList1.AddRange(allStudents.Select(a => new Person()
            {
               Age = a.Age,
               Name = a.Name
            } ));

TimeStape の値が allStundent リストに記載されていないすべての従業員を取得したい

var allEmployeesWithDifferentTimeStampThanStundent =
    allEmployee.Where(a => !allStudents.Select(b =>b.TimeStamp).Contains(a.TimeStamp));

再マッピング

personList2.AddRange(allEmployeesWithDifferentTimeStampThanStundent.Select
(a => new Person()
    {
    Age = a.Age,
    Name = a.Name
    } ));

両方のリストをマージする

personList1.AddRange(personList2);

これを行うためのより良い、より効率的な方法はありますか?

4

2 に答える 2

4

personList2変数は、型に射影するための中間としてのみ存在するように見えます。Personその場合は、その作成をスキップして、次のようなクエリ構文を使用できます。

var personsFromNonMatchingEmployees =
    from employee in allEmployee
    join student in allStudents
    on employee.TimeStamp equals student.TimeStamp into studentsWithMatchingTimeStamp
    where !studentsWithMatchingTimeStamp.Any()
    select new Person { Age = employee.Age, Name = employee.Name };

personList1.AddRange(personsFromNonMatchingEmployees);

これは、コンパイラが上記を GroupJoin 呼び出しに変換するため、他の GroupJoin アプローチと似ています。結合/グループ結合のWhere..Contains使用は、ハッシュを使用するため、必然的にアプローチよりも優れたパフォーマンスを発揮します。つまり、これはアルゴリズムの Big-O の改善であり、少数の Student または Employee インスタンスで非常に顕著になるはずです。

クエリでオブジェクトを選択することで、リストを完全new Personにバイパスできます。personList2私が本当に興味を持っているタイプにプロジェクトするこのような選択を行うことで、ほとんどの場合、一時リストを排除できることがわかりました。コンパイラはそれを必要としないため、 も省略しました()new Person { .. }

継承を変更して Employee : Person & Student : Person を作成するのが恥ずかしがり屋です。これ以上改善する必要はないと思います。

于 2013-01-29T03:39:58.857 に答える
2

同じタイムスタンプを持つGroupJoin一致するレコードがないすべての従業員を検索するために使用できます。Student

var employeesDiffTS = allEmployee
    .GroupJoin(allStudents, e => e.TimeStamp, s => s.TimeStamp, (e, students) => new { Emp = e, HasMatch = students.Any() })
    .Where(em => !em.HasMatch)
    .Select(em => em.Emp)

personList2.AddRange(employeeDiffTS.Select(a => new Person { Age = a.Age, Name = a.Name }));

personList1.AddRange(personList2);
于 2013-01-28T22:26:26.527 に答える