2012-05-25 2 views
1

Это кажется довольно простым, но я не могу сфокусироваться.
Скажем, у меня есть 2 классов, определенных следующим образом:Выберите из двух IEnumerables, используя LINQ

class Class1 
{ 
    public int Document; 
    public decimal Amount; 
} 

class Class2 
{ 
    public string Document; 
    public decimal Amount; 
} 

Есть IEnumerable<Class1> result1 и IEnumerable<Class2> result2 определены и заполнены данными.

У меня есть третий класс, определенный как это:

class ResultClass 
{ 
    public string Document; 
    public decimal? AmountFromClass1; 
    public decimal? AmountFromClass2; 
} 

Я хочу запрос LINQ, который выбирает некоторые поля из первого результата и некоторые поля из второго результата и помещает их в третьем результате определяется как List<ResultClass> result ,
Например, если у меня есть первый результат (result1) населенной, как это:

Document Amount 
    1   1.55 
    2   2.55 

и второй результат (result2) населенной, как это:

Document Amount 
    "d-1"  1.22 
    "d-2"  2.22 

Я хочу, чтобы иметь окончательный result (порядок не имеет значения):

Document AmountFromClass1 AmountFromClass2 
    "1"    1.55    null 
    "d-1"   null    1.22 
    "2"    2.55    null 
    "d-2"   null    2.22 

В настоящее время я делаю это с помощью двух foreach заявления, как это:

List<ResultClass> result = new List<ResultClass>(); 

foreach (var o in result1) 
    result.Add(new ResultClass 
    { 
     Document = o.Document.ToString(), 
     AmountFromClass1 = o.Amount, 
     AmountFromClass2 = null 
    }); 

foreach (var o in result2) 
    result.Add(new ResultClass 
    { 
     Document = o.Document, 
     AmountFromClass1 = null, 
     AmountFromClass2 = o.Amount 
    }); 

Но я хотел бы сделать это с помощью LINQ.
Возможно ли это?

EDIT: К УТОЧНИТЬ ВОПРОС (также добавил сущность-рамочный тег)
Поскольку это только пример кода, я знаю, что не может быть никаких реальных преимуществ делать это в одном LINQ поскольку он будет делать то же самое.
Однако я ищу улучшения производительности, где result1 и result2 на самом деле являются IQueryables от LINQ к Entities, таким образом, чтобы я мог сделать что-то вроде этого:

List<ResultClass> MyFunc() 
{ 
    Database DB = new Database(); // object context 
    var result1 = DB.Class1s.Where(...); 
    var result2 = DB.Class2s.Where(...); 
    return SomeMagic() 
     .Select(x => new ResultFunc { ... }) 
     .ToList(); 
} 
+2

Как видно из ответов, вы можете, безусловно, сделать это в LINQ, но это будет почти точно такое же количество кода, что работает практически точно так же эффективно. Я бы не стал менять его от вас; это просто прекрасно, как есть.Тем не менее, я бы добавил некоторые лишние пробелы в код, который у вас есть, а не пытаюсь сделать что-то в одной текстовой строке; это просто сложнее читать. – Servy

+0

@Servy Хороший комментарий, я помещаю новые строки и предпочитаю код, который легче читать, однако я был в спешке, когда набрал это, поэтому неудивительно, что это выглядит так. Сейчас я редактирую его. –

ответ

4

Проект каждого элемента в обеих коллекций ResultClass объекта и сцепить два полученных перечислимые:

var query1 = from o in result1 
      select new ResultClass 
      { 
       Document = o.Document.ToString(), 
       AmountFromClass1 = o.Amount 
      }; 

var query2 = from o in result2 
      select new ResultClass 
      { 
       Document = o.Document, 
       AmountFromClass2 = o.Amount 
      }; 

var result = query1.Concat(query2).ToList(); 
+0

Будет ли этот запрос фактически выполнен на 'select' или только на' ToList() ', если result1 и result2 будут IQueryables из linq для сущностей? –

1

Это вы коды преобразованы в LINQ

var result = result1 
    .Select(c => new ResultClass() { Document = c.Document.ToString(), AmountFromClass1 = c.Amount }) 
    .Concat(result2.Select(c => new ResultClass() { Document = c.Document, AmountFromClass2 = c.Amount })) 
    .ToList(); 
0

Основываясь на выходе вам, кажется, вам нужен Союз

 var class1 = new List<Class1>(); 
     var class2 = new List<Class2>(); 
     class1.Add(new Class1(){Document=1, Amount = 1.0M}); 
     class1.Add(new Class1(){Document=2, Amount = 1.0M}); 
     class2.Add(new Class2(){Document="1", Amount = 1.0M}); 
     class2.Add(new Class2(){Document="3", Amount = 1.0M}); 
      var result = class1.Select(x=> new ResultClass{Document = x.Document.ToString(), AmountFromClass1=x.Amount, AmountFromClass2 = null}).Union(
          class2.Select(x=> new ResultClass{Document = x.Document, AmountFromClass2=x.Amount, AmountFromClass1 = null}) ); 

Если вы хотите перекрестное соединение, то вы можете использовать синтаксис запросов с несколькими из пунктов. Example

Смежные вопросы