将重复的列折叠到子列表中

时间:2012-05-17 23:21:58

标签: c# database linq c#-4.0

将表格数据中的重复列折叠到列表中的最优雅方法是什么?

示例:我编写了一个SQL查询,该查询返回包含重复数据的行,但单个区分列除外:

FIRST   LAST      AGE   CAR
Charles Burns     32    Accord
Charles Burns     32    Buick
Charles Burns     32    Lexus
Anders  Hejlsberg 51    Porsche
Anders  Hejlsberg 51    Ferrari
Anders  Hejlsberg 51    Bugatti
Anders  Hejlsberg 51    Pinto

我使用以下内容读取这些内容,然后将它们放入CarInfo对象中:

while(reader.Read()) {
    first = reader["first"]
    last = reader["last"]
    //...
}
var myData = new CarInfo(first, last, ...);

该对象如下:

// CarInfo: Need 7 total instances with example data
string first { get; private set; }
string last { get; private set; }
int age { get; private set; }
string car { get; private set; }

我希望它看起来像:

// CarInfo: Need only 2 instances with example data; 
string first { get; private set; }
string last { get; private set; }
int age { get; private set; }
List<string> cars { get; private set; }

我当然可以手动执行此操作,例如选择形成唯一ID的列并检查它们是否已经在我的列表(或字典或其他)中,但这看起来非常费力。 我对LINQ非常熟悉,怀疑它可以很好地破坏这些数据,但还不够熟悉,无法想到一个确切的方法。

3 个答案:

答案 0 :(得分:1)

您是否尝试过Enumerable.GroupBy函数?这是你在寻找什么?

class A
        {
            public string a;
            public string b;
            public A(string x, string y)
            {
                a = x;
                b = y;
            }
        }
        static void Main(string[] args)
        {
            A[] tab = { new A("1", "1"), new A("2", "0"), new A("3", "1"), new A("4", "0"), new A("5", "1") };
            var g = tab.GroupBy(x => x.b);
            foreach (var x in g)
            {

                foreach (var y in x)
                {
                    Console.WriteLine(y.a + "/" + y.b);
                }
                Console.WriteLine("----");
            }
            Console.ReadKey();

        }

本守则返回:

{1,1}
{3,1}
{5,1}
--------
{2,0}
{4,0}

按字段b;

对元素进行分组

答案 1 :(得分:1)

您可以load a DataTable并使用LINQ-To-DataSet

List<CarInfo> cars = 
         (from cRow in tblCars.AsEnumerable()
          group cRow by new
          {
              first = cRow.Field<String>("first"),
              last  = cRow.Field<String>("last"),
              age   = cRow.Field<int>("age")
          }into CarGroup
          select new CarInfo() 
          { 
              first = CarGroup.Key.first,
              last  = CarGroup.Key.last,
              age   = CarGroup.Key.age ,
              cars  = CarGroup.Select(cRow => cRow.Field<String>("Car")).ToList()
          }).ToList();

以匿名类型上面的组,其中三个字段为关键字。然后使用这些字段初始化CarInfo个实例,并使用每个组中包含所有汽车的List<String>属性进行初始化。

答案 2 :(得分:0)

我昨天刚刚遇到这个问题,但我正在使用Dapper,这是SO使用的漂亮的对象映射器。它使用“拆分”方法,您必须指定要将父列与子列分隔的列或列列表:

List<CarInfo> parent = new List<CarInfo>();
CarInfo current = null;
var q = _conn.Query<CarInfo, string, CarInfo>(sql
    , (p, c0) =>
    {
        if (current == null || current.Id != p.Id)
        {
            current = p;
        }
        current.Cars.Add(c0);
        parents.Add(current);
        return current;
    }
    , splitOn: "CAR"
);