Можно ли упростить следующее выражение Linq? - PullRequest
0 голосов
/ 25 апреля 2020

Я должен поддерживать код, который сравнивает элементы двух коллекций

list1.Where(item1 => list2.Any(item2 => Cond1(item1,item2)) &&
    !list2.Any(item2 => Cond2(item1,item2)) 
)

Я пытался упростить все эти итерации и подумал, эквивалентен ли приведенный выше код следующему

list1.Where(item1 => list2.Any(item2 => Cond1(item1,item2) && !Cond2(item1,item2)))

Это кажется более управляемым, поэтому я попробовал несколько тестовых случаев, и первоначальные результаты были в порядке. Считаете ли вы, что это правда в целом, или вы можете определить ситуацию, когда нужен первый, более длинный код (= отличный от второго, более короткий)?

Изменить, чтобы отразить комментарии

Некоторые интересные замечания из комментариев.

  1. приведенное выше представляется эквивалентным тогда и только тогда, когда Cond1 определяет условие уникального ключа для list2, но, конечно, это не так в общем случае ,
  2. инвертирование порядка двух операторов Any представляется более эффективным, поскольку указывает Кн oop.

Относительно пункта 2, пожалуйста, Учтите, что более реалистичным c бизнес-кодом будет

list1.Where(item1 => list2.Any(item2 => Cond1(item1,item2)) &&
    !list2.Any(item2 => Cond1(item1,item2) && Cond2(item1,item2)) 
)

, потому что типичная бизнес-проблема, описанная здесь, состоит в сравнении двух коллекций и поиске пропущенных, совпадающих и разных записей, последней (другой - другой, но не отсутствующей). - записи) являющиеся тем, что сообщается в вопросе

1 Ответ

0 голосов
/ 26 апреля 2020

типичная бизнес-проблема, описанная здесь, сравнивает 2 коллекции и ищет пропущенные, совпадающие и разные записи, причем последние (разные - но не пропущенные) записи - это то, что сообщается в вопросе

Если вам нужно как функциональное, так и эффективное решение, вы можете использовать метод расширения Enumerable.Aggregate LINQ, как предлагается в аналогичном ответе , обернутом во внешний Where поверх первой коллекции list1.

(bool allVerified, bool anyVerified) = 
    list2.Aggregate( 
        ValueTuple.Create(true, false), 
        (tuple, item) => ValueTuple.Create(
            tuple.Item1 && !(Cond1(item1,item) && Cond2(item1,item)), 
            tuple.Item2 || Cond1(item1, item)) );
return allVerified && anyVerified;

Полный фрагмент скрипка здесь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...