{"id":5216,"date":"2021-08-03T12:57:05","date_gmt":"2021-08-03T11:57:05","guid":{"rendered":"https:\/\/solidt.eu\/site\/?page_id=5216"},"modified":"2025-04-17T16:28:31","modified_gmt":"2025-04-17T15:28:31","slug":"linq-helper","status":"publish","type":"post","link":"https:\/\/solidt.eu\/site\/linq-helper\/","title":{"rendered":"C# LinqHelper"},"content":{"rendered":"\n<div style=\"height: 250px; position:relative; margin-bottom: 50px;\" class=\"wp-block-simple-code-block-ace\"><pre class=\"wp-block-simple-code-block-ace\" style=\"position:absolute;top:0;right:0;bottom:0;left:0\" data-mode=\"csharp\" data-theme=\"monokai\" data-fontsize=\"14\" data-lines=\"Infinity\" data-showlines=\"true\" data-copy=\"false\">public static class LinqHelper\n{\n    public static IEnumerable&lt;T> Select&lt;T>(params T[] args) => args;\n    \n    public static IEnumerable&lt;T> SelectMany&lt;T>(params IEnumerable&lt;T>[] args) => args.SelectMany(x => x);\n\n    public static List&lt;T> List&lt;T>(params T[] args) => args.ToList();\n    \n    public static IEnumerable&lt;T> Init&lt;T>(int count, Func&lt;int, T> init) => Enumerable.Range(0, count).Select(i => init(i));\n    \n    public static IEnumerable&lt;IEnumerable&lt;T>> Split&lt;T>(IEnumerable&lt;T> src, int size) => src.Where((x, i) => i % size == 0).Select((x, i) => src.Skip(i * size).Take(size));\n    \n    public static bool HasSharedItem&lt;T>(IEnumerable&lt;T> left, IEnumerable&lt;T> right) => left.Any(l => right.Any(r => l != null &amp;&amp; r != null &amp;&amp; l.Equals(r)));\n\n    public static T GetValueIfExactOne&lt;T>(IEnumerable&lt;T> values, T defValue = default)\n    {\n        var distinct = values.Distinct();\n        return distinct.Count() == 1 ? distinct.First() : defValue;\n    }\n\n    public static async Task&lt;IEnumerable&lt;T>> FromAsync&lt;T>(IAsyncEnumerable&lt;T> items)\n    {\n        var list = new List&lt;T>();\n        await foreach (var item in items) { list.Add(item); }\n        return list;\n    }\n    \n    public static async Task&lt;IEnumerable&lt;U>> FromAsync&lt;T, U>(IAsyncEnumerable&lt;T> items, Func&lt;T, U> converter)\n    {\n        var list = new List&lt;U>();\n        await foreach (var item in items) { list.Add(converter(item)); }\n        return list;\n    }\n    \n    public static T MinOrDefault&lt;T>(this IEnumerable&lt;T> sequence, T defValue = default(T)) => sequence.Any() ? sequence.Min() : defValue;\n    public static T MaxOrDefault&lt;T>(this IEnumerable&lt;T> sequence, T defValue = default(T)) => sequence.Any() ? sequence.Max() : defValue;\n    \n    public static IEnumerable&lt;(T item, int index)> WithIndex&lt;T>(this IEnumerable&lt;T> self) => self.Select((item, index) => (item, index));\n\n    \/\/ filter where conditions in (Entity Framework) queries based on condition e.g:\n    \/\/ AsQueryable().WhereIf(onlyActiveItems, x => x.Active).ToListAsync();\n    public static IEnumerable&lt;TSource> WhereIf&lt;TSource>(this IEnumerable&lt;TSource> source, bool condition, Func&lt;TSource, bool> predicate) where TSource : class\n    {\n        return condition ? source.Where(predicate) : source;\n    }\n\n    public static IQueryable&lt;TSource> WhereIf&lt;TSource>(this IQueryable&lt;TSource> source, bool condition, Expression&lt;Func&lt;TSource, bool>> predicate) where TSource : class\n    {\n        return condition ? source.Where(predicate) : source;\n    }\n\n    public static IQueryable&lt;TSource> IncludeIf&lt;TSource, TProperty>(this IQueryable&lt;TSource> source, bool condition, Expression&lt;Func&lt;TSource, TProperty>> propertySelector) where TSource : class\n    {\n        return condition ? source.Include(propertySelector) : source;\n    }\n\n    public static IQueryable&lt;TSource> SkipIf&lt;TSource>(this IQueryable&lt;TSource> source, bool condition, int quantityToSkip) where TSource : class\n    {\n        return condition ? source.Skip(quantityToSkip) : source;\n    }\n    \n    public static IEnumerable&lt;T> SelectRecursive&lt;T>(this IEnumerable&lt;T> source, Func&lt;T, IEnumerable&lt;T>> recursiveSelector)\n    {\n        foreach (var i in source)\n        {\n            yield return i;\n\n            var directChildren = recursiveSelector(i);\n            var allChildren = SelectRecursive(directChildren, recursiveSelector);\n\n            foreach (var c in allChildren)\n            {\n                yield return c;\n            }\n        }\n    }\n\n    public static IQueryable&lt;TSource> TakeIf&lt;TSource>(this IQueryable&lt;TSource> source, bool condition, int quantityToTake) where TSource : class\n    {\n        return condition ? source.Take(quantityToTake) : source;\n    }\n    \n    public static Dictionary&lt;Y, T> ToDictionarySafe&lt;T, Y>(this IEnumerable&lt;T> items, Func&lt;T, Y> keySelector) => items.GroupBy(x => keySelector(x)).Where(x => x.Key != null).Select(x => x.First()).ToDictionary(x => keySelector(x));\n    \n\t\/\/ Comparable with: .GroupBy(x => x.Property).Select(x => x.First())\n\t\/\/ but possibly faster and with yield return\n\t\/\/ update: function exists in dotnet 6\n\tpublic static IEnumerable&lt;TSource> DistinctBy&lt;TSource, TKey>(this IEnumerable&lt;TSource> source, Func&lt;TSource, TKey> keySelector)\n\t{\n\t\tvar seenKeys = new HashSet&lt;TKey>();\n\t\tforeach (TSource element in source)\n\t\t\tif (seenKeys.Add(keySelector(element)))\n\t\t\t\tyield return element;\n\t}\n\t\n    public static bool ContainsDuplicates&lt;T>(this IEnumerable&lt;T> enumerable)\n    {\n        var knownKeys = new HashSet&lt;T>();\n        return enumerable.Any(item => !knownKeys.Add(item));\n    }\n\n    public static bool None&lt;T>(this IEnumerable&lt;T> list) => !list.Any();\n        \n\tpublic static IEnumerable&lt;int> GetRange(int min, int max)\n\t{\n\t\tfor (var i = min; i &lt;= max; i++)\n\t\t\tyield return i;\n\t}\n\n\tpublic static List&lt;List&lt;T>> Transpose&lt;T>(this IEnumerable&lt;IEnumerable&lt;T>> list)\n\t{\n\t\treturn list\n\t\t\t.SelectMany(inner => inner.Select((item, index) => new { item, index }))\n\t\t\t.GroupBy(i => i.index, i => i.item)\n\t\t\t.Select(g => g.ToList())\n\t\t\t.ToList();\n\t}\n\t\n\tpublic static (List&lt;T> TrueItems, List&lt;T> FalseItems) Partition&lt;T>(this IEnumerable&lt;T> source, Func&lt;T, bool> predicate)\n    {\n        var trueItems = new List&lt;T>();\n        var falseItems = new List&lt;T>();\n        foreach (var item in source)\n        {\n            if (predicate(item))\n                trueItems.Add(item);\n            else\n                falseItems.Add(item);\n        }\n        return (trueItems, falseItems);\n    }\n\n    \/\/ Cartesian product of two sets A and B, denoted A \u00d7 B, is the set of all ordered pairs\n    public static IEnumerable&lt;IEnumerable&lt;T>> Cartesian&lt;T>(IEnumerable&lt;IEnumerable&lt;T>> sequences)\n    {\n        return sequences.Aggregate(Enumerable.Repeat(Enumerable.Empty&lt;T>(), 1), (accumulator, sequence) => accumulator.SelectMany(acc => sequence.Select(item => acc.Append(item))));\n    }\n    \n    public static TimeSpan SumTimespan&lt;TSource>(this IEnumerable&lt;TSource> source, Func&lt;TSource, TimeSpan> predicate) => source.Select(predicate).Aggregate(TimeSpan.Zero, (a, c) => a + c);\n}<\/pre><\/div>\n\n\n\n<p>WhereIf example<\/p>\n\n\n\n<div style=\"height: 250px; position:relative; margin-bottom: 50px;\" class=\"wp-block-simple-code-block-ace\"><pre class=\"wp-block-simple-code-block-ace\" style=\"position:absolute;top:0;right:0;bottom:0;left:0\" data-mode=\"csharp\" data-theme=\"monokai\" data-fontsize=\"14\" data-lines=\"Infinity\" data-showlines=\"true\" data-copy=\"false\">\/\/ Original: query with separate if statements\npublic async Task&lt;IEnumerable&lt;PurchaseContractExpectedAndDelivered>> GetExpectedAndDeliveredQuantitiesForContract(PurchaseQuantityFilter filter)\n{\n\tusing var unitOfWork = GetUnitOfWork();\n\n\tvar query = Query&lt;DmPurchaseContractLine>(unitOfWork);\n\t\n\tif (filter.PurchaseContractId != null)\n\t\tquery = query.Where(x => x.PurchaseContractId == filter.PurchaseContractId)\n\t\t\n\tif (filter.PurchaseContractLineId != null)\n\t\tquery = query.Where(x => x.Id == filter.PurchaseContractLineId);\n\n\tvar selectQuery = query.Select(x => new PurchaseContractExpectedAndDelivered\n\t{\n\t\tPurchaseContractId = x.PurchaseContractId,\n\t\tPurchaseContractLineId = x.Id,\n\t\tExpectedKg = x.WeightKg,\n\t\tDeliveredKg = x.PurchaseShipments.Sum(x => x.WeightKg),\n\t\tDeliveredBoxes = x.PurchaseShipments.Sum(x => x.Boxes),\n\t});\n\n\treturn await selectQuery.ToListAsync();\n}\n\n\/\/ With an WhereIf: query as single statement\npublic async Task&lt;IEnumerable&lt;PurchaseContractExpectedAndDelivered>> GetExpectedAndDeliveredQuantitiesForContract(PurchaseQuantityFilter filter)\n{\n\tusing var unitOfWork = GetUnitOfWork();\n\n\tvar query = Query&lt;DmPurchaseContractLine>(unitOfWork)\n\t\t.WhereIf(filter.PurchaseContractId != null, x => x.PurchaseContractId == filter.PurchaseContractId)\n\t\t.WhereIf(filter.PurchaseContractLineId != null, x => x.Id == filter.PurchaseContractLineId);\n        .Select(x => new PurchaseContractExpectedAndDelivered\n    \t{\n    \t\tPurchaseContractId = x.PurchaseContractId,\n    \t\tPurchaseContractLineId = x.Id,\n    \t\tExpectedKg = x.WeightKg,\n    \t\tDeliveredKg = x.PurchaseShipments.Sum(x => x.WeightKg),\n    \t\tDeliveredBoxes = x.PurchaseShipments.Sum(x => x.Boxes),\n    \t});\n\n\treturn await query.ToListAsync();\n}<\/pre><\/div>\n\n\n\n<p>See also: <\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/solidt.eu\/site\/c-iasyncenumerable\/\">https:\/\/solidt.eu\/site\/c-iasyncenumerable\/<\/a>  <\/li>\n\n\n\n<li><a href=\"https:\/\/solidt.eu\/site\/c-async-selectforeach-with-yield-return\/\">https:\/\/solidt.eu\/site\/c-async-selectforeach-with-yield-return\/<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Example implementations for TakeWhile and TakeUntil<\/h2>\n\n\n\n<div style=\"height: 250px; position:relative; margin-bottom: 50px;\" class=\"wp-block-simple-code-block-ace\"><pre class=\"wp-block-simple-code-block-ace\" style=\"position:absolute;top:0;right:0;bottom:0;left:0\" data-mode=\"csharp\" data-theme=\"monokai\" data-fontsize=\"14\" data-lines=\"Infinity\" data-showlines=\"true\" data-copy=\"false\">public static class EnumerableExtensions\n{\n\t\/\/ TakeWhile exists in dotnet\n\tpublic static IEnumerable&lt;T> TakeWhile&lt;T>(this IEnumerable&lt;T> source, Func&lt;T, bool> predicate)\n    {\n        foreach (var item in source)\n        {\n            if (!predicate(item))\n\t\t\t\tyield break;\n            yield return item;\n        }\n    }\n\t\n    public static IEnumerable&lt;T> TakeUntil&lt;T>(this IEnumerable&lt;T> source, Func&lt;T, bool> predicate)\n    {\n        foreach (var item in source)\n        {\n            yield return item;\n            if (predicate(item))\n                yield break;\n        }\n    }\n}<\/pre><\/div>\n","protected":false},"excerpt":{"rendered":"<p>WhereIf example See also: Example implementations for TakeWhile and TakeUntil<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"footnotes":""},"categories":[6,4,1],"tags":[],"class_list":["post-5216","post","type-post","status-publish","format-standard","hentry","category-dotnet","category-programming","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/posts\/5216","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/comments?post=5216"}],"version-history":[{"count":31,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/posts\/5216\/revisions"}],"predecessor-version":[{"id":9455,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/posts\/5216\/revisions\/9455"}],"wp:attachment":[{"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/media?parent=5216"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/categories?post=5216"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/tags?post=5216"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}