3
void Main()
    {
        List<SomeContainer> someList = new List<SomeContainer>();
        someList.Add(new SomeContainer { a = true, b = true, c = true });
        someList.Add(new SomeContainer { a = false, b = true, c = false });
        someList.Add(new SomeContainer { a = true, b = true, c = false });
        someList.Add(new SomeContainer { a = true, b = false, c = false });
        someList.Add(new SomeContainer { a = true, b = false, c = false });
        someList.Add(new SomeContainer { a = true, b = true, c = false });
        someList.Add(new SomeContainer { a = true, b = true, c = false });

        var q1 = from container in someList where container.a == true select container.a;
        var q2 = from container in someList where container.b == true select container.b;
        var q3 = from container in someList where container.c == true select container.c;
        q1.Count().Dump();
        q2.Count().Dump();
        q3.Count().Dump();
    }

    class SomeContainer
    {
        public Boolean a { get; set; }
        public Boolean b { get; set; }
        public Boolean c { get; set; }
    }

is it possible to generate something like this with one querry:
a | b | c
6 | 5 | 1

4 Answers 4

4

Not sure whether you will treat this as optimization, but this will iterate over your list only once:

var result = someList
        .Select(i => new [] {i.a? 1:0, i.b? 1:0, i.c? 1:0,})
        .Aggregate((i, acc) => new [] {i[0]+acc[0], i[1]+acc[1], i[2]+acc[2]});

int countA = result[0];
int countB = result[1];
int countC = result[2];
Sign up to request clarification or add additional context in comments.

3 Comments

+1 this answers the question, I'd personally settle for int aCount = someList.Count(x => x.a); (b,c) though for readability.
@BrokenGlass, agree, but it wasn't about readability. It is anyway good to know this idea since it works with plain SQL also so it can optimize regular SQL queries.
Now I know everything about Aggregate. BrokenGlass's solution rocks for it's simplicity. Thanks for quick response.
1
int a = 0, b = 0, c = 0;
var qAll = (from ct in someList
            select new{ ac  = ct.a ? a++ : 0,  
                        bc =  ct.b ? b++ : 0,
                        cc = ct.c ? c++ : 0}).ToList();

//Now a, b, c variables should have the count of a==true, b==true & c==true in somelist.
//Console.WriteLine("A= {0}, B={1}, C={2}", a, b, c);

1 Comment

So it is possible to do it in one query! Perfect solution.
0

The Aggregate extension methods allow you combine values from enumerables in arbitrary ways. You can aggregate a tuple of three integers representing a count, and provide a function that will increment the three counters on the tuple depending on the input.

It suspect it may could look contrived for this example, and it may be slower than a regular for loop.

Sometimes Aggregate shines though. I used it to compute the bounding rectangle of a list of rectangles: var union = rects.Aggregate(Rectangle.Union);

Comments

0
someList.Count(container => container.a).Dump();
someList.Count(container => container.b).Dump();
someList.Count(container => container.c).Dump();
//even when looking for false values it looks nice...
someList.Where(container => container.a == false).Count(container => container.a).Dump();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.