Поиск элементов в одном списке, но не в другом, в точном порядке

#c# #linq

#c# #linq

Вопрос:

Я бы предположил, что для этого есть простой запрос LINQ, я просто не совсем уверен, как это сделать. Пожалуйста, смотрите фрагмент кода ниже, комментарий объясняет, что я хотел бы сделать:

 class Program
{
    static void Main(string[] args)
    {
        List<Person> peopleList1 = new List<Person>();
        peopleList1.Add(new Person() { ID = 1 });
        peopleList1.Add(new Person() { ID = 2 });
        peopleList1.Add(new Person() { ID = 3 });

        List<Person> peopleList2 = new List<Person>();
        peopleList2.Add(new Person() { ID = 2 });
        peopleList2.Add(new Person() { ID = 1 });
        peopleList2.Add(new Person() { ID = 4 });
        peopleList2.Add(new Person() { ID = 3 });
        peopleList2.Add(new Person() { ID = 5 });
    }
}
  

Я хотел бы выполнить запрос LINQ, чтобы предоставить мне всех людей, peopleList1 которых нет peopleList2 в том же порядке
, в котором этот пример должен дать мне трех человек:

(ID = 1, 2 и 3)

Я попытался использовать

 peopleList1.Except(peopleList2)
  

Но это не работает в моем сценарии, потому что я также должен проверять порядок. Список 1 должен содержать элемент в той же позиции, что и список 2

Комментарии:

1. Вы пробовали что-нибудь?

2. Я пробовал Except, но он не проверяет порядок.

3. Что вы подразумеваете под «точным положением»??

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

5. Пока я понимаю… есть два списка, которые содержат объекты одного и того же типа, идентификатор является ключевым между обоими. Вы хотите проверить все записи в одном списке на соответствие всем записям в другом или под «точной позицией» вы имеете в виду, что вы хотите проверить, что элемент проверки в позиции 1 в списке 1 должен быть снова проверен «только» элемент в позиции 1 в списке 2???

Ответ №1:

В .NET List<T> тип поддерживается массивом, поэтому наиболее эффективным способом сделать это с помощью LINQ было бы использовать перегрузку Select , которая также обращается к индексу:

 peopleList1.Where((person, index) => peopleList2[index].Id != person.Id);
  

Комментарии:

1. Да, в исходном примере нет элементов, которые отображаются с одинаковым индексом в обоих списках!

2. Вы проверяли это с данными OP? Потому что, когда я тестировал это, это не дает мне трех человек (ID = 1, 2 и 3), как упоминал OP!

3. Ах, я пропустил «не» часть его сообщения! Все, что нужно сделать, это изменить значение == to != в лямбда

4. Также вам нужно изменить peopleList2[index] peopleList2[index].Id , чтобы этот код работал.

5. Готово! Я только что использовал int список при тестировании и забыл добавить его обратно

Ответ №2:

Я думаю, это должно быть то, что вы хотите:

 var result = peopleList1.Zip(peopleList2, (f, s) => f.ID != s.ID ? f.ID : 0)
                        .Where(c => c > 0).ToList();
  

Zip Проверяет соответствующие элементы peopleList1 и peopleList2 , и выдает последовательность результатов, которая представляет собой элементы, которые существуют, peopleList1 но не peopleList2 в том же порядке.

Ответ №3:

Это должно сделать

 peopleList1.Where(x=>peopleList2.Count<peopleList1.IndexOf(x) 1||peopleList2[peopleList1.IndexOf(x)].ID!=x.ID).ToList()
  

Комментарии:

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

2. Но это не дает результата для примера OP.

3. Если бы были какие-либо совпадения, он вернул бы список элементов, которые совпали, в противном случае список был бы пустым. попробуйте изменить образец данных, чтобы получить совпадение, а затем проверить результат.

4. например, сделайте идентификаторы первых элементов 1 и 2 соответственно в обоих списках и test.

5. Вы проверяли это с данными OP? Потому что, когда я тестировал это, это не дает мне трех человек (ID = 1, 2 и 3), как упоминал OP!