Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Actually accepted answer enumerates your items collection <code>2N + 1</code> times and it adds unnecessary complexity to your original solution. If I'd met this piece of code</p> <pre><code>(from t in items let confirmedQty = items.Where(o =&gt; o.IsConfirmed == true).Sum(u =&gt; u.Qty) let unconfirmedQty = items.Where(o =&gt; o.IsConfirmed != true).Average(u =&gt; u.Qty) let total = confirmedQty + unconfirmedQty select new { tl = total }).FirstOrDefault(); </code></pre> <p>it would take some time to understand what type of data you are <strong>projecting</strong> items to. Yes, this query is a strange projection. It creates <code>SelectIterator</code> to project each item of sequence, then it create some range variables, which involves iterating items twice, and finally it selects first projected item. Basically you have wrapped your original queries into additional useless query:</p> <pre><code>items.Select(i =&gt; { var confirmedQty = items.Where(o =&gt; o.IsConfirmed).Sum(u =&gt; u.Qty); var unconfirmedQty = items.Where(o =&gt; !o.IsConfirmed).Average(u =&gt; u.Qty); var total = confirmedQty + unconfirmedQty; return new { tl = total }; }).FirstOrDefault(); </code></pre> <p><em>Intent is hidden</em> deeply in code and you still have same two nested queries. What you can do here? You can simplify your two queries, make them more <em>readable</em> and show your <em>intent</em> clearly:</p> <pre><code>int confirmedTotal = items.Where(i =&gt; i.IsConfirmed).Sum(i =&gt; i.Qty); // NOTE: Average will throw exception if there is no unconfirmed items! double unconfirmedAverage = items.Where(i =&gt; !i.IsConfirmed).Average(i =&gt; i.Qty); int total = confirmedTotal + (int)unconfirmedAverage; </code></pre> <p>If <em>performance</em> is more important than readability, then you can calculate total in single query (moved to extension method for readability):</p> <pre><code>public static int Total(this IEnumerable&lt;Item&gt; items) { int confirmedTotal = 0; int unconfirmedTotal = 0; int unconfirmedCount = 0; foreach (var item in items) { if (item.IsConfirmed) { confirmedTotal += item.Qty; } else { unconfirmedCount++; unconfirmedTotal += item.Qty; } } if (unconfirmedCount == 0) return confirmedTotal; // NOTE: Will not throw if there is no unconfirmed items return confirmedTotal + unconfirmedTotal / unconfirmedCount; } </code></pre> <p>Usage is simple:</p> <pre><code>items.Total(); </code></pre> <p>BTW Second solution from accepted answer is not correct. It's just a coincidence that it returns correct value, because you have all unconfirmed items with equal <code>Qty</code>. This solution calculates sum instead of average. Solution with grouping will look like:</p> <pre><code>var total = items.GroupBy(i =&gt; i.IsConfirmed) .Select(g =&gt; g.Key ? g.Sum(i =&gt; i.Qty) : (int)g.Average(i =&gt; i.Qty)) .Sum(); </code></pre> <p>Here you have grouping items into two groups - confirmed and unconfirmed. Then you calculate either sum or average based on group key, and summary of two group values. This also neither readable nor efficient solution, but it's correct.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload