Как выполнить 2 проверки в LINQ Где - PullRequest
1 голос
/ 04 декабря 2009
public List<SavedOption> GetValidSavedOptions(
    List<Option> itemOptions, 
    List<SavedOption> savedOptions)
{
    List<SavedOption> finalSavedOptions = savedOptions.Where(x => 
        OptionTextDoesMatch(y, x) && 
        itemOptions.Any(y => y.SomeID == x.SomeID)
    ).ToList(); 
}

Я совершенно новичок в LINQ и Lambdas.

В вышеприведенном, что мне нужно / нужно сделать, это включить SavedOption, только если вызов OptionTextDoesMatch AND SomeID из savedOption найден в списке SomeID в itemOptions , Если вызов OptionTextDoesMatch возвращает true И текущий savedOptions SavedOption.SomeID найден в коллекции itemOption, то он будет в ToList()

ОБНОВЛЕНИЕ:

Я попробовал это, но синтаксис все еще не работает для меня:

saveOptions.Where (itemOptions.Any (OptionTextDoesMatch (x, y) && (y => y.SomeID == x.SomeID))). ToList ();

Теперь я не знаю, смогу ли я просто так добавить x. Я предполагаю, что если я это сделаю, это будет представлять текущий сохраненный вариант, и мне не нужно =>?

Ответы [ 3 ]

6 голосов
/ 04 декабря 2009

Хотя приведенные выше ответы правильные , они представляют собой ответы "дай человеку рыбу". Было бы лучше воспользоваться этой возможностью, чтобы узнать, как разбить проблему на маленькие части, а затем собрать результаты в запросы.

В вышесказанном, что мне нужно / хочу сделать включить SavedOption, только если вызов OptionTextDoesMatch AND SomeID сохраненного варианта находится в список SomeID в itemOptions.

Позвольте мне попытаться перефразировать это чье-то запутанное предложение.

У вас есть список SavedOptions. Каждый SavedOption имеет идентификатор и текст.

У вас есть список опций. Каждый параметр имеет идентификатор и текст.

Вы хотите отфильтровать список SavedOptions, чтобы получить SavedOptions, которые соответствуют некоторому Option для ОБА и текста и идентификатора.

Устранить проблему. Предположим, у вас не было последовательности SavedOptions. Предположим, у вас только один вариант SavedOption и список опций. Как бы вы сказали, если это был матч?

Это просто:

SavedOption mySavedOption = whatever;
bool matchExists = itemOptions.Any(item=>
    OptionTextDoesMatch(item, mySavedOption) && 
    item.SomeID == mySavedOption.SomeID);

Имеет ли это смысл?

Теперь предположим, что вы хотите сделать предикат из того, что требует SavedOption. Как бы вы это сделали? Это просто:

Func<SavedOption, bool> predicate = savedOption => 
    itemOptions.Any(item=>
        OptionTextDoesMatch(item, savedOption ) && 
        item.SomeID == savedOption.SomeID);

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

Все еще имеет смысл? Остановите меня, если что-то смущает.

Чтобы сделать из него фильтр, примените предикат к каждому элементу в списке сохраненных опций :

result = savedOptions.Where(savedOption => 
    itemOptions.Any(item=>
        OptionTextDoesMatch(item, savedOption) && 
        item.SomeID == savedOption.SomeID));

Или в форме для понимания запросов, которую мне лично легче читать.

result = from savedOption in savedOptions
         where itemOptions.Any(item =>
             OptionTextDoesMatch(item, savedOption) && 
             item.SomeID == savedOption.SomeID)
         select savedOption;

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

result = from savedOption in savedOptions
         join itemOption in itemOptions 
         on savedOption.SomeID equals itemOption.SomeID
         where OptionTextDoesMatch(itemOption, savedOption)
         select savedOption;

Это ясно?

3 голосов
/ 04 декабря 2009

Случайная догадка:

List<SavedOption> finalSavedOptions = savedOptions.Where(x => 
    itemOptions.Any(y => OptionTextDoesMatch(y, x) && y.SomeID == x.SomeID)
).ToList(); 
1 голос
/ 04 декабря 2009

В вашем предложении Where вы итерируете каждый объект в вашем методе SavedOptions - так же, как если бы вы это сделали:

foreach(SavedOption x in savedOptions)
{
    if (OptionTextDoesMatch(y, x)) //y is not yet specified...
    {
        foreach(Option y in itemOptions)
        {
            if (y.SomeID == x.SomeID)
                yield return x;
        }
    }
}

В вашем утверждении предложение where выполняет итерацию списка сохраненных вариантов и для каждой итерации присваивает текущему экземпляру сохраненной опции значение 'x'. Затем вы проверяете, что текст 'x соответствует тому, что вы еще не указали -' y '.

Затем вы делаете вторую итерацию: itemOptions.Any(y => y.SomeID == x.SomeID). Здесь вы указали, что y теперь определяется как экземпляр Option почти так же, как вы делали это с внешним лямбда-выражением:

foreach(Option y in itemOptions)
{
    return y.SomeID == x.SomeID;
}

Поскольку x определяется внешним предложением, у нас есть доступ к нему во внутреннем предложении, но обратное неверно. y не указывается до внутреннего предложения, поэтому ваше предложение where не работает.

Чтобы дать полную диагностику того, что вы пытаетесь сделать, мне нужно понять, как выглядят объекты Option и SavedOptions, и выяснить, что вы логически пытаетесь сделать, чтобы точно объяснить, как ваша лямбда должна выглядеть ...

Я подозреваю, что вы действительно пытаетесь сделать что-то вроде:

foreach(SavedOption x in savedOptions)
    foreach(Option y in itemOptions)
        if (OptionTextDoesMatch(y, x) && (y.SomeID == x.SomeID))
            yield return x;

Что было бы в лямбда-записи:

return savedOptions.Where(x => itemOptions.Any(y => OptionTextDoesMatch(y, x) && (y.SomeID == x.SomeID)));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...