C# 合并两个列表<;T>;使用LINQ基于实例成员合并T的实例

C# 合并两个列表<;T>;使用LINQ基于实例成员合并T的实例,c#,.net,linq,generics,join,C#,.net,Linq,Generics,Join,我有一个名为NamedEntity的抽象类(由各种不同的子类覆盖): public抽象类NamedEntity其中T:TweetModel { 受保护的字符串\u名称; 公共抽象字符串名称{get;set;} 公共摘要列表tweets{get;set;} } 这个类中的关键元素是列表,它包含一个Tweet对象列表,用于对与Tweet相关的基本元数据(即文本、作者、日期/时间等)进行建模 如何组合两个列表,以便根据Name属性的匹配值将一个列表中的项目合并到另一个列表中 即NamedEntity

我有一个名为NamedEntity的抽象类(由各种不同的子类覆盖):

public抽象类NamedEntity其中T:TweetModel
{
受保护的字符串\u名称;
公共抽象字符串名称{get;set;}
公共摘要列表tweets{get;set;}
}
这个类中的关键元素是
列表
,它包含一个Tweet对象列表,用于对与Tweet相关的基本元数据(即文本、作者、日期/时间等)进行建模

如何组合两个
列表
,以便根据Name属性的匹配值将一个列表中的项目合并到另一个列表中

即NamedEntity1的名称为“伦敦”+相关tweetsNamedEntity2的名称为“伦敦”和不同的
列表。如何合并这两个集合,然后从两个集合中提取
列表
实例,并将它们添加到新的
列表
对象中

我已经读到我可以在这里使用连接,但我并不真正理解LINQ语法:

private List<NamedEntity<TweetModel>> joinLists(List<NamedEntity<TweetModel>> list1, List<NamedEntity<TweetModel>> list2)
{
    //var joined = from Name in list1 join Name in list2 on ????;
}
私有列表joinlist(列表列表1、列表列表2)
{
//var join=从列表1中的名称在???上连接列表2中的名称????;
}

有三件事你需要告诉
加入
:加入哪些集合,通过什么和如何实际加入它们:

private IEnumerable<NamedEntity<TweetModel>> Join(
    IEnumerable<NamedEntity<TweetModel>> list1,
    IEnumerable<NamedEntity<TweetModel>> list2)
{
    return list1.Join(list2, item => item.Name, item => item.Name, (outer, inner) =>
    {
        outer.tweets.AddRange(inner.tweets);
        return outer;
    });
}
私有IEnumerable连接(
IEnumerable列表1,
IEnumerable列表2)
{
返回list1.Join(list2,item=>item.Name,item=>item.Name,(外部,内部)=>
{
外部.tweets.AddRange(内部.tweets);
返回外部;
});
}
您可以使用
Union()
组合这两个
列表
,按
名称
对它们进行分组,并使用
tweets
属性选择新对象,该属性填充了相应组中所有
tweets
的组合:

private List<NamedEntity<TweetModel>> joinLists(List<NamedEntity<TweetModel>> list1, List<NamedEntity<TweetModel>> list2)
{
    List<NamedEntity<TweetModel>> joined;

    joined = list1.Union(list2)
                  .GroupBy(o => o.Name)
                  .Select(o => new NamedEntity<TweetModel>
                                 {
                                     Name = o.Key,
                                     tweets =
                                         o.SelectMany(x => x.tweets).ToList()
                                 }).ToList();

    return joined;
}
私有列表joinlist(列表列表1、列表列表2)
{
加入名单;
joined=list1.Union(list2)
.GroupBy(o=>o.Name)
.选择(o=>新名称身份
{
名称=o.键,
推特=
o、 选择many(x=>x.tweets).ToList()
}).ToList();
回归加入;
}

这样可以避免在某种情况下丢失一些
NamedEntity
s,例如,当示例中的
NamedEntity1
NamedEntity2
位于相同的
列表中时。对于普通LINQ连接(因为它基本上是一个内部连接),将只返回两个列表中都存在
Name
NamedEntity

您始终可以选择只使用嵌套的传统foreach循环。您甚至可以创建一个扩展方法来合并两个列表:

public static class NamedEntityExtensions
{
    public static IList<NamedEntity<T>> MergeEntities<T>(this IList<NamedEntity<T>> list1, IList<NamedEntity<T>> list2)
        where T: TweetModel
    {
        foreach(NamedEntity<T> entity1 in list1)
        {
            foreach(NamedEntity<T> entity2 in list2)
            {
                if(entity1.Name == entity2.Name)
                {
                    entity1.Tweets.AddRange(entity2.Tweets);
                }
            }
        }

        return list1; //original list will get augmented but returning it allows chaining
    }
}
此方法还支持将调用链接到两个以上的列表:

list1.MergeEntities(list2).MergeEntities(list3);
如果您不想实际修改原始列表1,则始终可以在扩展方法内部生成一个新列表,而不是添加到原始列表中


注意:只有当列表1包含您关心的所有不同的“Name”值时,这才有效。需要添加额外的逻辑,才能从仅存在于列表2中的实体创建新项。

如何解决无法在
中创建(抽象)NamedEntity类实例的问题。选择
表达式?
list1.MergeEntities(list2);
list1.MergeEntities(list2).MergeEntities(list3);