将列表<object>和list <otherobject>组合成单个平面列表</otherobject> </object>

时间:2014-06-27 14:49:18

标签: c# linq list

我有一个对象,其中包含另一个对象列表的成员。 即:

public class ObjA
{
    public int Id { get; set; }
    Other members....
    public List<ObjB> ObjBs{ get; set; }
}

public class ObjB
{
  public int Id { get; set; }
  Other members...
}

我目前正在foreach中填充ObjA对象,然后在foreach循环中调用另一个foreach填充ObjB列表并将其添加到ObjA中的ObjBs成员。

理想情况下,我想要一个ObjA的平面列表,其中所有相关的ObjB(按ID)附加到列表中。这是可能的,我在所有ObjA和所有ObjB的页面中都有临时列表,只是不确定如何将它们加入到动态的单个平面列表中?

希望这有道理吗?

3 个答案:

答案 0 :(得分:3)

好吧,它必须只是一个List<object>,但这应该有效:

// Flat list of ObjB
var referenced = listA.SelectMany(x => x.ObjBs);

// Concatenate listA with the flat list of ObjB
var flat = listA.Concat<object>(referenced).ToList();

答案 1 :(得分:0)

修改

根据您的评论,它看起来像你想要的那样:

IEnumerable<object[]> output = listA.Select(a => (new []{a}).Cast<object>()
                                                            .Concat(a.ObjBs) 
                                                            .ToArray());

var output = listA.Select(a => (new [] {new {a.Id}})
                                          .Concat(a.ObjBs.Select(b => new {b.Id}));
                             );

原始答案

这是一个单行,虽然它不在您指定的顺序中(如果这很重要):

IEnumerable<object> output = listA.SelectMany(a => a.ObjBs
                                                    .Cast<object>()
                                                    .Concat(new [] {a}) );

或者如果要创建具有公共属性的匿名类型:

var output = listA.SelectMany(a => a.ObjBs.Select(b => new {b.Id})
                                          .Concat(new [] {new {a.Id}})
                             );

通过这种方式,您至少可以访问公共属性而无需进行强制转换或反射。

答案 2 :(得分:0)

如果你想要它们按照第一个A的顺序那么它的&#39; Bs,第二个A然后是Bs等。

var flat = listA.SelectMany(a => new List<object> {a}.Concat(a.ObjBs)).ToList();

必须是List<object>