1

私はクラスプロジェクトを持っています

public class Project 
{   public int ProjectId { get; set; }
    public string ProjectName { get; set; }
    public string Customer { get; set; }
    public string Address{ get; set; }
}

そして私は3つのリストを持っています

List<Project> lst1; List<Project> lst2; List<Project> lst3;

lst1PersonProjectId と ProjectName を持つオブジェクトが含まれます。

ProjectId =1, ProjectName = "X", Customer = null, Address = null

ProjectId =2, ProjectName = "Y", Customer = null, Address = null

lst2PersonProjectId と Customer を持つオブジェクトが含まれています

ProjectId =1,ProjectName = null, Customer = "c1", Address = null

ProjectId =2,ProjectName = null, Customer = "c2", Address = null 、 と

lst3PersonProjectId と Address を持つオブジェクトが含まれています

ProjectId = 1, ProjectName = null, Customer =null, Address = "a1"

ProjectId = 2, ProjectName = null, Customer =null, Address = "a2".

各リストにそのようなレコードが複数あり、ProjectId が各プロジェクトの Uniqe であることを考慮すると、これらのリストをマージ/結合して、マージされたオブジェクトを含む 1 つのリストを取得するにはどうすればよいですか?

ProjectId=1, ProjectName="X", Customer="c1", address="a1"

ProjectId=2, ProjectName="Y", Customer="c2", address="a2"

これらのリンクが似ていることがわかり、試してみましたが、結果を満たすことができませんでした

linq を使用して 2 つのオブジェクト リストからリストを作成する

LINQ を使用して 2 つのリストをマージする方法は?

ありがとうございました。

4

6 に答える 6

2

ルックアップを使用すると、次のように実行できます。

        List<Project> lst = lst1.Union(lst2).Union(lst3).ToLookup(x => x.ProjectId).Select(x => new Project()
        {
            ProjectId = x.Key,
            ProjectName = x.Select(y => y.ProjectName).Aggregate((z1,z2) => z1 ?? z2),
            Customer = x.Select(y => y.Customer).Aggregate((z1, z2) => z1 ?? z2),
            Address = x.Select(y => y.Address).Aggregate((z1, z2) => z1 ?? z2)
        }).ToList();
于 2012-05-29T12:45:42.477 に答える
1

やり過ぎですが、これを拡張メソッドにしたくなりました。

public static List<T> MergeWith<T,TKey>(this List<T> list, List<T> other, Func<T,TKey> keySelector, Func<T,T,T> merge)
{
    var newList = new List<T>();
    foreach(var item in list)
    {
        var otherItem = other.SingleOrDefault((i) => keySelector(i).Equals(keySelector(item)));
        if(otherItem != null)
        {
            newList.Add(merge(item,otherItem));
        }
    }
    return newList;
}

使用法は次のようになります。

var merged = list1
     .MergeWith(list2, i => i.ProjectId,
       (lhs,rhs) => new Project{ProjectId=lhs.ProjectId,ProjectName=lhs.ProjectName, Customer=rhs.Customer})
    .MergeWith(list3,i => i.ProjectId,
       (lhs,rhs) => new Project{ProjectId=lhs.ProjectId,ProjectName=lhs.ProjectName, Customer=lhs.Customer,Address=rhs.Address});

実際の例: http://rextester.com/ETIVB14254

于 2012-05-29T12:36:21.470 に答える
1

リストには同じ数のアイテムが含まれており、ProjectId で並べ替えられていると想定しています。

List<Project> lst1; List<Project> lst2; List<Project> lst3

リストがソートされていない場合は、最初にソートできます。

list1.Sort(p => p.ProjectId);
list2.Sort(p => p.ProjectId);
list3.Sort(p => p.ProjectId);

オブジェクトのマージ用

List<Project> list4 = new List<Project>();
for(int i=1; i<list.Count; i++)
{ 
    list4.Add(new Project
    {
       ProjectId = list1[i].ProjectId;
       ProjectName = list1[i].ProjectName;
       Customer = list2[i].Customer;
       Address = list3[i].Address;
    });

}
于 2012-05-29T12:19:18.027 に答える
1

LINQのJoin仕組みは次のとおりだと思います:

var mergedProjects =
    lst1
        .Join(lst2,
            proj1 => proj1.ProjectID,
            proj2 => proj2.ProjectID,
            (proj1, proj2) => new { Proj1 = proj1, Proj2 = proj2 })
        .Join(lst3,
            pair => pair.Proj1.ProjectID,
            proj3 => proj3.ProjectID,
            (pair, proj3) => new Project
            {
                ProjectID = proj3.ProjectID,
                ProjectName = pair.Proj1.ProjectName,
                Customer = pair.Proj2.Customer,
                Address = proj3.Address
            });

3 つのリストすべてProjectIDに が見つからない場合、結果は返されません。

これが問題になる場合は、LINQ を使用するよりも手動で行う方がよいと思います。

于 2012-05-29T12:23:19.410 に答える
0

これは、最初のnull以外の値を取得するか、デフォルト値(この場合は文字列の場合はnull)に戻すことを前提としています。

private static IEnumerable<Project> GetMergedProjects(IEnumerable<List<Project>> projects)
{
    var projectGrouping = projects.SelectMany(p => p).GroupBy(p => p.ProjectId);
    foreach (var projectGroup in projectGrouping)
    {
        yield return new Project
                            {
                                ProjectId = projectGroup.Key,
                                ProjectName =
                                    projectGroup.Select(p => p.ProjectName).FirstOrDefault(
                                        p => !string.IsNullOrEmpty(p)),
                                Customer =
                                    projectGroup.Select(c => c.Customer).FirstOrDefault(
                                        c => !string.IsNullOrEmpty(c)),
                                Address =
                                    projectGroup.Select(a => a.Address).FirstOrDefault(
                                        a => !string.IsNullOrEmpty(a)),
                            };
    }
}

必要に応じて、これを拡張メソッドにすることもできます。

于 2012-05-29T13:08:23.510 に答える