2015-03-17 2 views
-4

У меня есть 3 списка.Получите уникальные элементы из нескольких списков, используя LINQ-C#

ListA<items> 
ListB<items> 
ListC<items> 

я должен выбрать один элемент из каждого списка, но item.itemID должен быть уникальным для каждого из этих элементов. Как я могу достичь этого? Заранее спасибо.

+0

использование [Concat] (https://msdn.microsoft.com/en-us/library/bb302894 (v = vs.110) .aspx), затем [Distinct] (HTTPS: //msdn.microsoft.com/en-us/library/vstudio/bb348436(v=vs.100).aspx) – Grundy

+3

Distinct будет работать только в том случае, если он делает сравнение, или ссылки на объекты одинаковы или элементы представляют собой структуру – TheCatWhisperer

+0

@TheCatWhisperer Distinct работает, если объекты сопоставимы - не только одни и те же ссылки или структура или простой obejct. Однако concat + distinct не соответствует его критериям. –

ответ

1
List<items> concat = new List<items>(); 
concat.AddRange(ListA); 
concat.AddRange(ListB); 
concat.AddRange(ListC); 

List<items> result = new List<items>(); 
foreach (var item in concat) 
{ 
    if (result.Where(x => x.itemId == item.itemId).Count() == 0) 
    { 
     result.add(item); 
    } 
} 
//result should now contain what you are looking for 
+0

Это не сработает, потому что оно может содержать несколько ответов от ListA, а не по одному из каждого списка. –

+0

Мне нужно получить один элемент из каждого списка. Я не думаю, что эта логика позаботится об этом требовании, поскольку списки объединены здесь. –

1

Так что вы хотите точно один элемент из каждого списка, в котором не был выбран этот пункт уже из предыдущего списка?

Затем выберите из списков, где идентификатор отсутствует в предыдущем выборе. Может быть, что-то вроде этого:

var itemA = listA.First(); // any item is unique, since this is our first one 
var itemB = listB.First(b => b.ID != itemA.ID); 
var itemC = listC.First(c => c.ID != itemA.ID && c.ID != itemB.ID); 

Если количество списков не известно, тогда мы должны были бы сделать это немного более динамичным. Может быть, что-то вроде этого:

var selectedItems = new List<Item>(); 
foreach (var list in listOfLists) 
    selectedItems.Add(list.First(x => selectedItems.Count(y => y.ID == x.ID) == 0)); 

Что это делает петлю через «список списков» (так как количество списков не известно, она должна быть в структуре сбора данных) и получить первый элемент из каждый из которых имеет известные совпадающие идентификаторы. Это должно привести к отображению одного выбранного элемента из каждого списка.

(Все это предполагает, что списки содержат действительный элемент, который вы ищете. Если это не так, то вы можете использовать FirstOrDefault() вместо и проверить нули.)

+0

Это не сработает, если списки являются {A, B, C}, {B, C, D}, {A, B}. Результат должен быть C, D, A или C, D, B или B, D , A или B, C, A и т. Д. –

+0

Это хорошо работает в моем сценарии. Благодарю. –

0
public class items 
{ 
    public int id {get;set;} 
} 
void Main() 
{ 
    var l1=new List<items>{new items {id=1}, new items {id=2}, new items {id=3}}; 
    var l2=new List<items>{new items {id=2}, new items {id=3}, new items {id=4}}; 
    var l3=new List<items>{new items {id=1}, new items {id=2}}; 
    var result=l1 
      .Join(l2,(k1)=>true,(k2)=>true,(a1,a2)=>new {a1,a2}) 
      .Join(l3,(k1)=>true,(k2)=>true,(b1,b2)=>new {b1.a1,b1.a2,a3=b2}) 
      .Where(rec=>rec.a1.id!=rec.a2.id && rec.a2.id!=rec.a3.id && rec.a1.id!=rec.a3.id) 
      .First(); 
    Console.WriteLine("{0},{1},{2}",result.a1.id,result.a2.id,result.a3.id); 
} 

Из возможных ответов (132,142,231,241,321,341,342) он будет выбирать и возвращать первый (132).

Пример кода: http://csharppad.com/gist/98a076bdd4e01dbd82be