2015-09-03 7 views
0

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

List<UserEntry> list1 = new List<UserEntry>(); 
list1.Add(new UserEntry { login = "1", requestorList = new List<string>() { "1", "2", "3" } }); 
     list1.Add(new UserEntry { login = "2", requestorList = new List<string>() { "1", "4", "3" } }); 
     list1.Add(new UserEntry { login = "3", requestorList = new List<string>() { "1", "2", "3" } }); 

Я хочу, чтобы найти элементы, которые имеют такое же requestorList и сгруппировать их во втором списке. В приведенном выше примере первый и третий элементы имеют 1,2,3.

Я попробовал это, и это не работает:

for (int i = 0; i < list1.Count; i++) 
     { 
      var kar = list1.ElementAt(i); 
      for (int j = 0; j < list1.Count; j++) 
      { 
      if(kar.requestorList.Equals(list1.ElementAt(j).requestorList)) 
       { 
        list2.Add(kar); 
       } 
      } 
     } 

EDIT: secoond Список должен иметь только два элемента, так как первый один и третий имеют одинаковые requestorLists

+0

Почему это не работает? Что вы получаете вместо того, что вы ожидали? – Sossenbinder

+0

все элементы из List1 копируются в List2 – user576914

+2

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

ответ

1

Если вы хотите получить список вы хотите, фантазии делают это:

Прежде всего, вам нужно добавить второй, если, например:

if(list1.ElementAt(i).Equals(list1.ElementAt(j))){ 
    continue; 
} 

, чтобы пропустить случаи, когда вы сравнили бы элемент с самим собой.

Кроме того, если вы не хотите дубликаты, используйте это вместо того, чтобы только делать list2.Add(kar);:

if(!list2.Contains(kar)){ 

    list2.Add(kar); 
} 

Edit: Полный код должен выглядеть примерно так, если я не испортит:

for (int i = 0; i < list1.Count; i++) 
     { 
      var kar = list1.ElementAt(i); 
      for (int j = 0; j < list1.Count; j++) 
      { 
      if(kar.requestorList.SequenceEqual(list1.ElementAt(j).requestorList)) 
       { 
        if(list1.ElementAt(i).Equals(list1.ElementAt(j))){ 
          continue; 
        } 

        if(!list2.Contains(kar)){ 

         list2.Add(kar); 
        } 
       } 
      } 
     } 
+0

Я пробовал ваш код, но теперь второй список не содержит никаких элементов. – user576914

+2

Проверка равенства списков не проверяет их элемент за элементом. Используйте SequenceEqual вместо Equals. –

+0

Я тоже этого не знал. Надеюсь, я отредактировал это правильно. К сожалению, я не могу проверить это прямо сейчас, но по крайней мере этот код - вот что я сейчас придумаю – Sossenbinder

0

Есть несколько проблем, с кодом:

  • Вы можете использовать индексатор для доступа к элементу из вместо ElementAt(), который является более вербальным. Он выглядит чище для меня
  • Equals() сравнивает только ссылку вашего списка, а не контент. Таким образом, ["1", "2", "3"] и ["1", "3", "2"] выдадут ложное значение
  • Иначе вы сравниваете элемент в списке1 с собой, как и другие ответы

Вот моя попытка с помощью LINQ:

var list2 = list1.GroupBy(e => 
        e.requestorList.OrderBy(r => r)  //Order list ascending 
            .Aggregate((i, j) => i + j)) //Append elements in the list together to create "signature" of the list 
        .Where(g => g.Count() > 1)   //Select grouping that has at least 2 elements 
        .SelectMany(g => g);   //Flatten all the lists into single list 

Я использую OrderBy() и Aggregate() для создания своего рода "подписи" для requestorList, так что [ "1", "3", «2»] и [«1», «2», «3»], имеющие одну и ту же подпись «123», затем группируют элементы по этой подписи

Не уверен, что вы ожидаете в list2, так что я просто расплющить все, что есть дубликаты requestorList в единый список

+0

Первый порядок может быть важен, хотя это не очевидно из примера. Второй вместо «Агрегат» лучше использовать 'string.Join', и вы хотите использовать разделитель, чтобы [" 1 "," 2 "] не был равен [" 12 "] – juharr

1

Это ваш код с небольшой разницей

for (int i = 0; i < list1.Count; i++) 
     { 
      var kar = list1.ElementAt(i); 
      for (int j = i+1; j < list1.Count; j++) 
      { 
       if (Enumerable.SequenceEqual(kar.requestorList.OrderBy(t => t), list1.ElementAt(j).requestorList.OrderBy(t => t))) 
       { 
        list2.Add(kar); 
        list2.Add(list1.ElementAt(j)); 
       } 
      } 
     } 
Смежные вопросы