开发者

reduce number of LINQ queries

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


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];


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);


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);


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();
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜