Home > Blockchain >  IQueryable conditional GroupBy
IQueryable conditional GroupBy

Time:09-10

I am attempting to build a groupby based on condition however I have been unsuccessful.

IQueryable<MyObject> query ..
var returnedVal = query.GroupBy(y => new {
                            Val1 = !first ? y.Val1 : null,
                            Val2 = !second ? y.Val2 : null })
                 .Select(x => new MyObject {
                            Val1 = !first ? y.Key.Val1 : null,
                            Val2 = !second ? y.Key.Val2 : null });
id Val1 Val2
1 Sta test1
2 Danny test2
3 Elle test2
4 Elle test3

Scenario 1: first: false second false
GroupBy both Val1 and Val2
Return all 4 rows

Scenario 2: first: true second false
GroupBy only Val2
Return 3 rows (test1, test2, test3)

Scenario 3: first: false second true
GroupBy only Val1
Return 3 rows (Sta, Danny, Elle)

Scenario 4: first: true second true
GroupBy nothing
Return nothing

My problem is that everytime either "first" or "second" is true Val1 and Val2 still gets included in the groupby of the query. Is setting Val1/Val2 to null in the GroupBy the right approach to exclude it from the groupby entirely?

CodePudding user response:

I don't see the actual problem, because you don't tell if the result is what you expect. If you just want to remove the unnecessary grouping, use an if:

if(condition){ queryWithBothProperties } else { queryWithOneProperty }

The bool flags are not related to the records, so you can easily leave them out of the query.

On that way the query might become more efficient:

if (first && second)
{
    // no grouping necessary since all would be null anyway
    result = query
        .Select(x => new MyObject { Val1 = x.Val1, Val2 = x.Val2 });
}
else if (first)
{
    result = query
        .GroupBy(x => x.Val2)
        .Select(g => new MyObject { Val1 = null, Val2 = g.Key });
}
else if (second)
{
    result = query
        .GroupBy(x => x.Val1)
        .Select(g => new MyObject { Val1 = g.Key, Val2 = null });
}
else
{
    // both are false, you want to group by both properties
    result = query
          .GroupBy(x => (x.Val1, x.Val2))
          .Select(x => new MyObject { Val1 = x.Key.Val1, Val2 = x.Key.Val2 });
}

CodePudding user response:

It's really hard to tell what you're trying to solve without an example value of Val1 and Val2, and the expected output. That said, here's some Linqpad code that might be what you're going for - or at least provide a starting point to describe a few test cases...

var list = new List<(int id, string val1, string val2)>()
    {(1, "Sta", "test1"),
    (2, "Danny", "test2"),
    (3, "Elle", "test2"),
    (4, "Elle", "test3")};

var first = "Danny";
var second = "test3";


list
.Where(row => row.val1 != first && row.val2 != second)
.GroupBy(row => new { row.val1, row.val2 })
.Select(row => new
{
    Val1 = row.Key.val1,
    Val2 = row.Key.val2, 
    RowVals = string.Join(',', row)
})
.Dump();

Results

Val1 Val2 RowVals
Sta test1 1, Sta, test1
Elle test2 3, Elle, test2
  • Related