Выбор LINQ отличается от 4 списков IEnumerable - PullRequest
2 голосов
/ 09 июня 2009

Представьте себе четыре списка, у всех по крайней мере есть это строковое свойство Id, но могут быть и другие свойства:

public class A //or B, C, D
{
    public string Id { get; set; }
    //..other properties
}

//so:  
List<A> a1 = new List<A>();
List<B> a2 = new List<B>();
List<C> a3 = new List<C>();
List<D> a4 = new List<D>();

Я хочу выбрать все идентификаторы DISTINCT в: а1, в сочетании с а2, а3 и а4

Я думал, что синтаксис LINQ будет идеальным, но как объединить их в результат IEnumerable с одним строковым свойством, например с определением класса A.

Ответы [ 5 ]

9 голосов
/ 09 июня 2009

Поскольку это разные типы, я бы сначала выбрал свойство Id , чтобы получить IEnumerable , а затем объединил результаты:

var query = a1.Select(a=> a.Id)
              .Concat(a2.Select(b=> b.Id))
              .Concat(a3.Select(c=> c.Id))
              .Concat(a4.Select(d=> d.Id))
              .Distinct();
4 голосов
/ 13 июня 2009

Union

Конечно, вы можете упростить это:

var uniqueIds = (from a in a1
                 select a.Id).Concat(
                 from b in a2
                 select b.Id).Concat(
                 from c in a3
                 select c.Id).Concat(
                 from d in a4
                 select d.Id).Distinct();

Используя Union (который подразумевает «Distinct»), чтобы стать:

var uniqueIds =  (from a in a1
                 select a.Id).Union(
                 from b in a2
                 select b.Id).Union(
                 from c in a3
                 select c.Id).Union(
                 from d in a4
                 select d.Id);
4 голосов
/ 09 июня 2009

Это также работает:

new[] {a1, a2, a3, a4}.SelectMany(x => x.Select(y => y.Id)).Distinct();
3 голосов
/ 09 июня 2009

Это действительно все списки одного типа? Или у вас есть

List<A> a1 = new List<A>();
List<B> a2 = new List<B>();
List<C> a3 = new List<C>();
List<D> a4 = new List<D>();

и вы хотите объединить их, потому что все 4 типа имеют общее свойство идентификатора строки?

ОК, ваши изменения показывают, что я был на правильном пути. Вам необходим интерфейс, который определяет свойство строкового идентификатора, и каждый тип A, B, C и D должен реализовывать этот интерфейс.

Тогда каждый список будет иметь тип интерфейса, и будут работать конкретные ответы.

Если у вас нет возможности определить интерфейс, вы можете использовать LINQ для запроса каждого списка только для поля Id (вы должны получить IQueryable<String> результаты) и затем объединить эти результаты.

Edit: вот запрос LINQ, который должен дать вам то, что вы ищете:

var uniqueIds = (from a in a1
                 select a.Id).Concat(
                 from b in a2
                 select b.Id).Concat(
                 from c in a3
                 select c.Id).Concat(
                 from d in a4
                 select d.Id).Distinct();
2 голосов
/ 09 июня 2009

Вы можете объединить IEnumerables того же типа, а затем выбрать нужный элемент.

var query = a1
    .Concat(a2)
    .Concat(a3)
    .Concat(a4)
    .Select(a => a.ID)
    .Distinct();

РЕДАКТИРОВАТЬ: на основе нового вопроса ... Выбор из различных типов списка невозможно в одном запросе. Лучший способ сделать это - иметь общий тип, включающий выбранное вами свойство, а затем выполнить вышеуказанный запрос с базовым типом.

...