none
не выходит запрос LINQ :) RRS feed

  • Вопрос

  • Не могу найти примера, нужно сравнить два списка по полю id и:

    1) Из списка 1 удалить все объекты, отсутствующие в списке 2

    2) Добавить в список 1 все объекты из списка 2, которые отсутствуют в списке 1

    Ну и вдогонку :)

    После 1) нужно эти "лишние" объекты вообще уничтожить (чтобы вызвался деструктор) или вызвать их определённый метод

    После 2) опять же, нужно вызвать определённый метод именно добавленных объектов (но тут не обязательно, т.к. могу пройтись вообще по всему списку с этим методом)

    И совсем последнее :) здесь написано, что подобные запросы изменят только переменную, а не существующий список. якобы нужно пользоваться RemoveAll()объясните, пожалуйста, что это значит и почему так происходит?

    Заранее крайне благодарен! :)

    19 сентября 2012 г. 14:42

Ответы

  • Тут уже посложнее будет, но если с предыдущим разобрались, то и с этим не проблема.

    namespace ConsoleApplication
    {
      class Program
      {
        static void Main(string[] args)
        {
          List<MyClass> list1 = new List<MyClass>() 
          { 
            new MyClass(){ Id = 1},
            new MyClass(){ Id = 2},
            new MyClass(){ Id = 3},
            new MyClass(){ Id = 4},
            new MyClass(){ Id = 5}
          };
          List<MyClass> list2 = new List<MyClass>() 
          { 
            new MyClass(){ Id = 4},
            new MyClass(){ Id = 5},
            new MyClass(){ Id = 6},
            new MyClass(){ Id = 7},
            new MyClass(){ Id = 8}
          };
    
          //Из списка 1 удалить все объекты, отсутствующие в списке 2
           IEnumerable<MyClass> newList1 = list1.Where(i => list2.Contains(list2.Where(j=> j.Id == i.Id).FirstOrDefault()));
           foreach (var a in newList1)
             Console.Write(a.Id);
          //Вывод 4 5
           Console.Write("\n");
          //Добавить в список 1 все объекты из списка 2, которые отсутствуют в списке 1
           IEnumerable<MyClass> newList2 = list1.Concat(list2.FindAll(i=> !list1.Select(j=> j.Id).Contains(i.Id)));
           foreach (var b in newList2)
             Console.Write(b.Id);
           //Вывод 1 2 3 4 5 6 7 8
           Console.Write("\n");
    
          //нужно эти "лишние" объекты вообще уничтожить (чтобы вызвался деструктор) 
          //или вызвать их определённый метод
           list1.RemoveAll(i => !list2.Contains(list2.Where(j => j.Id == i.Id).FirstOrDefault()));
           foreach (var c in list1)
             Console.Write(c.Id);
           //Вывод 4 5
           Console.Write("\n");
        }
      }
      class MyClass
      {
        public int Id { get; set; }
      }
    }

    • Изменено YatajgaEditor 19 сентября 2012 г. 19:47
    • Помечено в качестве ответа Kenaut 19 сентября 2012 г. 19:50
    19 сентября 2012 г. 19:46
    Модератор

Все ответы

  • Так например:

    namespace ConsoleApplication
    {
      class Program
      {
        static void Main(string[] args)
        {
          List<int> list1 = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9,10 };
          List<int> list2 = new List<int>() { 2, 4, 6, 8};
    
          //Из списка 1 удалить все объекты, отсутствующие в списке 2
          int[] containsList2 = list1.Where(i => !list2.Contains(i)).ToArray();
    
          //Добавить в список 1 все объекты из списка 2, которые отсутствуют в списке 1
          int[] containsList1List2 = list1.Concat(list2.Where(i => !list1.Contains(i))).ToArray();
    
          //нужно эти "лишние" объекты вообще уничтожить (чтобы вызвался деструктор) 
          //или вызвать их определённый метод
          list1.RemoveAll(i=>true);
          list2.RemoveAll(i=>true);
        }
      }
    }

    "И совсем последнее :) здесь написано, что подобные запросы изменят только переменную, а не существующий список. якобы нужно пользоваться RemoveAll()объясните, пожалуйста, что это значит и почему так происходит?" - можно очистить весь список, один элемент или по определённому критерию, в коде я это показал.

    19 сентября 2012 г. 15:52
    Модератор
  • Yatajga, спасибо за ответ, а если не int, а объекты вида

    class A {
         int id;
    }
    ?

    и list1.RemoveAll(i=>true) все объекты удалит, я имел в виду в одном запросе (ну или компактно как-нить) уничтожить те объекты, которые будут удалены здесь: list1 = list1.Where(i => !list2.Contains(i)).ToArray()

    типа такого: l1.RemoveAll (c => !l2.Exists (cr => cr.id == c.id));

    • Изменено Kenaut 19 сентября 2012 г. 18:50
    19 сентября 2012 г. 18:11
  • Тут уже посложнее будет, но если с предыдущим разобрались, то и с этим не проблема.

    namespace ConsoleApplication
    {
      class Program
      {
        static void Main(string[] args)
        {
          List<MyClass> list1 = new List<MyClass>() 
          { 
            new MyClass(){ Id = 1},
            new MyClass(){ Id = 2},
            new MyClass(){ Id = 3},
            new MyClass(){ Id = 4},
            new MyClass(){ Id = 5}
          };
          List<MyClass> list2 = new List<MyClass>() 
          { 
            new MyClass(){ Id = 4},
            new MyClass(){ Id = 5},
            new MyClass(){ Id = 6},
            new MyClass(){ Id = 7},
            new MyClass(){ Id = 8}
          };
    
          //Из списка 1 удалить все объекты, отсутствующие в списке 2
           IEnumerable<MyClass> newList1 = list1.Where(i => list2.Contains(list2.Where(j=> j.Id == i.Id).FirstOrDefault()));
           foreach (var a in newList1)
             Console.Write(a.Id);
          //Вывод 4 5
           Console.Write("\n");
          //Добавить в список 1 все объекты из списка 2, которые отсутствуют в списке 1
           IEnumerable<MyClass> newList2 = list1.Concat(list2.FindAll(i=> !list1.Select(j=> j.Id).Contains(i.Id)));
           foreach (var b in newList2)
             Console.Write(b.Id);
           //Вывод 1 2 3 4 5 6 7 8
           Console.Write("\n");
    
          //нужно эти "лишние" объекты вообще уничтожить (чтобы вызвался деструктор) 
          //или вызвать их определённый метод
           list1.RemoveAll(i => !list2.Contains(list2.Where(j => j.Id == i.Id).FirstOrDefault()));
           foreach (var c in list1)
             Console.Write(c.Id);
           //Вывод 4 5
           Console.Write("\n");
        }
      }
      class MyClass
      {
        public int Id { get; set; }
      }
    }

    • Изменено YatajgaEditor 19 сентября 2012 г. 19:47
    • Помечено в качестве ответа Kenaut 19 сентября 2012 г. 19:50
    19 сентября 2012 г. 19:46
    Модератор
  • Спасибо! сэкономили мне кучу времени :)
    19 сентября 2012 г. 19:51
  • Могу ошибаться, но первую проблему (это удаление отсутсвующий элементов) можно решить с помощью Enumerable.Intersect<tsource></tsource> - метод (IEnumerable<tsource></tsource>, IEnumerable<tsource></tsource>) (это пересечение множеств, как раз останутся только общие элементы для 1го и 2го множества).

    Для связи [mail]

    20 сентября 2012 г. 10:01