2014-11-17 1 views
1

У меня есть аналогичные следующие данные структурыLinq запрос, который проверяет на наличие в нескольких списках

var blueList = new [] 
    { 
     new { Id = 1, Value = 1000 }, 
     new { Id = 2, Value = 1300 }, 
     new { Id = 3, Value = 1500 }, 
     new { Id = 5, Value = 2100 } 
    }.ToList(); 

var redList = new [] 
    { 
     new { Id = 1, Value = 600 }, 
     new { Id = 3, Value = 950 }, 
     new { Id = 4, Value = 1100 }, 
     new { Id = 5, Value = 1300 } 
    }.ToList(); 

var greenList = new [] 
    { 
     new { Id = 1, Value = 50 }, 
     new { Id = 2, Value = 180 }, 
     new { Id = 3, Value = 270 }, 
     new { Id = 4, Value = 430 }, 
     new { Id = 5, Value = 510 } 
    }.ToList(); 

var colourList = new [] { blueList, redList, greenList }.ToList(); 

colourList может содержать abritrary число элементов, а они только что произошло, чтобы быть названным в данном конкретном случае.

Как создать запрос linq, который даст мне новый список, который содержит только «Идентификаторы», которые находятся во всех группах в списке?

Следующий результат исключает Id = 2, поскольку он не находится в redList и Id = 4, потому что он не находится в синем списке. Это то, что мне нужно.

var result = new [] 
    { 
     new { Id = 1, Values = new [] { 1000, 600, 50 } }, 
     new { Id = 3, Values = new [] { 1500, 950, 270 } }, 
     new { Id = 5, Values = new [] { 2100, 1300, 510 } } 
    }; 

Любые предложения?

+2

какое усилие вы сделали? –

+0

Если вы задаете вопрос, который я редко делаю, я стараюсь как можно короче поставить вопрос, а также попытаюсь представить его в форме, которую кто-то может легко скопировать и вставить разделы в консольное приложение для тестирования. Если никто не ответит на ответ, я добавлю свое решение. –

+0

, так что если у вас есть решение, зачем задавать вопрос в первую очередь? –

ответ

4

Easy:

var query = 
    colourList 
     .Select(xs => xs.Select(x => new 
     { 
      Id = x.Id, 
      Values = Enumerable.Repeat(x.Value, 1), 
     })) 
     .Aggregate((xs, vs) => 
      from x in xs 
      join v in vs on x.Id equals v.Id 
      select new 
      { 
       Id = x.Id, 
       Values = x.Values.Concat(v.Values), 
      }); 

Я получаю этот результат на данных выборки:

result

Конечно, вы можете расширить colorList содержать столько подсписки, как вам нравится.

+0

Это, безусловно, работает. Теперь мне просто нужно опустить голову;) –

+0

Хороший ответ. Может быть, легко читать, но вы не можете сказать мне, что это легко написать, по крайней мере, для неспециалиста. : p –

+0

Принимая ваш ответ, поскольку это единственный запрос linq. Теперь ваше решение имеет смысл, и это интересно, потому что в отличие от того, как я буду атаковать проблему. Благодарю. –

1

Это, кажется, работает нормально:

var ids = new List<int>(); 

if (colourList != null && colourList.Any()) 
{ 
    // Grab all ids from the first list 
    ids = colourList[0].Select(c => c.Id).ToList(); 

    // Save only the intersection with each additional list 
    ids = colourList.Aggregate(ids, (cl1, cl2) => 
     cl1.Intersect(cl2.Select(c => c.Id)).ToList()); 
} 

Console.WriteLine("The common ids are: {0}", string.Join(", ", ids)); 
1

Я только что пришел с этим. Он просто взял меня немного времени, чтобы получить мою голову в двойной Любой

var idsInAllColour = 
    from colour in colourList 
    from id in colour 
    where colourList.All(cli => cli.Any(ci => ci.Id == id.Id)) 
    group id by id.Id; 
+1

Возможно, вы захотите изучить [законы Де Моргана] (https://en.wikipedia.org/wiki/De_Morgan%27s_laws): '! List.Any (x => condition)' такое же, как 'list.All (x =>! condition) '. В вашем случае это 'where colourList.All (cli => cli.Any (ci => ci.Id == id.Id))'. – svick

+1

Кроме того, вы можете избавиться от этой последней части 'в g select g'. – svick

+0

Спасибо за ваши улучшения –

1

Я сделал это в два этапа:

  • НАЙДИТЕ отдельными идентификаторами
  • для каждого отдельного ID, фильтр с идентификаторами, которые во всех списках

    var distinctIds = colourList.SelectMany(o => o).Select(o => o.Id).Distinct(); 
    
    var matchingIds = distinctIds.Where(id => colourList.All(l => l.Select(o => o.Id).Contains(id))); 
    

Тогда я г EAD других ответов и понял, что вам нужно только отдельные идентификаторы из первого списка:

var matchingIds = colourList 
         .First() 
         .Where(j => colourList 
             .Skip(1) 
             .All(l => l.Any(k => j.Id == k.Id)) 
           ) 
         .Select(j => j.Id); 

Вот .NET скрипки:

https://dotnetfiddle.net/4pPcDO

0

Вот еще один!

var commonIds = 
    colorList.SelectMany(cList => cList, (c, id) => new {c, id}) 
      .Where(cList => !colorList.Any(c => c.All(cl => cl.Id != cList.id.Id))) 
      .GroupBy(cList => cList.id.Id, cList => cList.id) 
      .Select(cList => cList.Key) 
      .ToList(); 

Console.WriteLine(string.Join(", ", commonIds)); 
1

Я придумал этот solution.:-

var result = colourList.SelectMany(x => x) 
         .GroupBy(x => x.Id) 
         .Where(x => x.Count() == colourList.Count()) 
         .Select(x => new { Id = x.Key, Values = String.Join(",", x.Select(z => z.Value)) }); 

Вот полный Fiddle.

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