2012-05-17 2 views
2

Каков самый элегантный способ свернуть дубликаты столбцов из табличных данных в списки?Свернуть кратные столбцы в подсписке

Пример: Я написал запрос 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; } 

Я могу, конечно, сделать это вручную, например, путем выбора столбцов, которые образуют уникальный идентификатор и проверить, если они уже находятся в моем списке (или словарь или любой другой) , но это кажется очень трудоемким. Я достаточно хорошо знаком с LINQ, чтобы заподозрить, что он может красиво свернуть эти данные, но не достаточно хорошо знаком для точного метода, который приходит на ум.

ответ

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> со всеми автомобилями на группу.

0

Вчера я столкнулся с этой проблемой, но использовал Dapper, красивый объект mapper, используемый 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" 
); 
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} 

Группировка элемент с помощью поля Ь;