Reputation: 67898
NOTE: I've changed the names of the collections because of confidentiality.
Consider the following code:
o.Flag =
o2.Collection1
.Any(cpd => cpd.Collection1
.Any(plc => plc.Collection1
.Any(vd => vd.DetailedFlag))) ||
o2.Collection1
.Any(cpd => cpd.Collection2
.Any(plc => plc.Collection1
.Any(vd => vd.DetailedFlag)));
Clearly what I'm doing is flattening the detailed flags into an overall flag, but this code as is iterates o2.Collection1
twice.
I don't see how SelectMany
can do the job because the flags are on two different collections (i.e. I'm not flattening a collection of collections).
How can I keep from doing that?
NOTE: I feel like Jon Skeet, when I read this post (Using LINQ to flatten a hierarchical dataset - with a caveat) was basically saying I'm stuck. But hopefully I'm reading it wrong!
Upvotes: 0
Views: 128
Reputation: 203827
If the collections are of the same type (or have a common base type defining sufficient information) you can simply concat them in your query:
o.Flag =
o2.Collection1
.Any(cpd => cpd.Collection1.Concat(cpd.Collection2)
.Any(plc => plc.Collection1
.Any(vd => vd.DetailedFlag)));
Note that the primary advantage here is simply making a simpler query, and reducing code duplication. It's not going to have any noticeable effect on how well it performs as long as your collection is actually an in memory collection
If they are not of compatible types (or there are subtle differences in the predicates for each sub-collection, unlike the example given), then the best that you can manage is to pull both sub-queries into the predicate of the main collection:
o.Flag =
o2.Collection1
.Any(cpd => cpd.Collection1
.Any(plc => plc.Collection1
.Any(vd => vd.DetailedFlag)) ||
cpd.Collection2
.Any(plc => plc.Collection1
.Any(vd => vd.DetailedFlag)));
Upvotes: 6
Reputation:
You could use a single iteration up till the first layer, then branch into two separate queries.
o.Flag =
o2.Collection1
.Any(cpd => cpd.Collection1
.Any(plc => plc.Collection1
.Any(vd => vd.DetailedFlag)) ||
cpd.Collection2
.Any(plc => plc.Collection1
.Any(vd => vd.DetailedFlag)));
Upvotes: 4