С# Объединение нескольких элементов LINQ для поиска пользователя

Я пытаюсь добавить пользователя в команду, выполнив поиск по списку пользователей.

Я использую linq для поиска данных, чтобы найти совпадение на основе ряда полей.

data = data.Where(x =>
                    x.Name.ToLower().Contains(filter) ||
                    x.Surname.ToLower().Contains(filter) ||
                    x.PhoneNumber.ToLower().Contains(filter) ||
                    x.Email.ToLower().Contains(filter) ||
                    x.AthleteTeams.All(x => x.Team.Name.Contains(filter)) ||
                    x.AthleteTeams.All(x => x.Athlete.AthleteGender.Equals(filter)) ||
                    x.AthleteTeams.All(x => x.Athlete.AthleteRace.Equals(filter))
                );

Однако результаты работают только с именем, фамилией и электронной почтой.

При поиске по всем полям выдаются, казалось бы, случайные пользователи, а не те, которые соответствуют указанному фильтру.

Он возвращает, казалось бы, случайных пользователей вместо тех, которые соответствуют указанному фильтру --> Можете ли вы привести конкретный пример сценария и указать значения для data, filter, ожидаемого результата и фактического результата?

Astrid E. 15.02.2023 13:54

Вы уверены, что вам нужно All, а не Any. Обратите внимание, что All для пустой коллекции всегда верно в LINQ-to-Objects.

Guru Stron 15.02.2023 13:56

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

Myles Louw 15.02.2023 13:57

@MylesLouw Это недостаточно конкретные примеры данных. Поскольку у вас есть много условий ИЛИ, существует так много потенциальных совпадений, которые можно сделать. Кроме того, в одних местах вы используете .ToLower(), а в других нет. Это предназначено? filter был .ToLower()ed?

Astrid E. 15.02.2023 14:00
Типы данных JavaScript
Типы данных JavaScript
В JavaScript существует несколько типов данных, включая примитивные типы данных и ссылочные типы данных. Вот краткое объяснение различных типов данных...
Как сделать движок для футбольного матча? (простой вариант)
Как сделать движок для футбольного матча? (простой вариант)
Футбол. Для многих людей, живущих на земле, эта игра - больше, чем просто спорт. И эти люди всегда мечтают стать футболистом или менеджером. Но, к...
Знайте свои исключения!
Знайте свои исключения!
В Java исключение - это событие, возникающее во время выполнения программы, которое нарушает нормальный ход выполнения инструкций программы. Когда...
CSS Flex: что должен знать каждый разработчик
CSS Flex: что должен знать каждый разработчик
CSS Flex: что должен знать каждый разработчик Модуль flexbox, также известный как гибкий модуль разметки box, помогает эффективно проектировать и...
Введение в раздел "Заголовок" в HTML
Введение в раздел "Заголовок" в HTML
Говорят, что лучшее о человеке можно увидеть только изнутри, и это относится и к веб-страницам HTML! Причина, по которой некоторые веб-страницы не...
1
4
52
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Однако результаты работают только с именем, фамилией и электронной почтой.

Я думаю, что PhoneNumber тоже должно быть хорошо.

При поиске по всем полям выдаются, казалось бы, случайные пользователи, а не те, которые соответствуют указанному фильтру.

Enumerable.All для пустой коллекции всегда будет true:

Console.WriteLine(new int[]{}.All(i => false)); // prints True

Попробуйте использовать что-то вроде:

data = data.Where(x =>
    ... || (x.AthleteTeams.Any() && (
    x.AthleteTeams.All(x => x.Team.Name.Contains(filter)) ||
    x.AthleteTeams.All(x => x.Athlete.AthleteGender.Equals(filter)) ||
    x.AthleteTeams.All(x => x.Athlete.AthleteRace.Equals(filter))))
);

Также, возможно, вам действительно нужно Any вместо All в первую очередь:

data = data.Where(x =>
    ... 
    || x.AthleteTeams.Any(x => x.Team.Name.Contains(filter) 
             || x.Athlete.AthleteGender.Equals(filter)
             ||  x.Athlete.AthleteRace.Equals(filter))
);
Ответ принят как подходящий

Я предполагаю, что вы не хотите, например, найти всех пользователей, которые AthleteTeams имеют ВСЕ одинаковое имя команды. Это будет означать, что у вас есть несколько команд с похожим названием.

Я предполагаю, что вы на самом деле хотите найти всех пользователей, которые AthleteTeams содержат хотя бы ОДНУ команду с совпадающим именем, например. Поэтому используйте Any, а также используйте только один запрос AthleteTeams вместо трех:

 ....
 x.AthleteTeams.Any(x => x.Team.Name.Contains(filter)
                     ||  x.Athlete.AthleteGender.Equals(filter)
                     ||  x.Athlete.AthleteRace.Equals(filter))

Однако я нахожу эту логику фильтра странной и подверженной ошибкам. У вас будет медленная производительность поиска и много ложных совпадений, потому что всегда что-то совпадает, а пользователь не знает, почему. Лучше предоставьте поиск по наиболее распространенным свойствам, таким как имена и номер телефона, не начинайте поиск, пока пользователь не введет как минимум 3 символа, и предоставьте конкретный поиск по команде.

Другие вопросы по теме