Reputation: 18259
EDIT
I'm going to illustrate the exact problem I'm trying to solve. The simplified problem explanation wasn't working.
I'm writing a framework that requires me to assign threads to CPU cores based on load factor. Please let's not debate the point as to why I'm doing this.
When the framework boots, it forms a map of the following hardware:
I represent this with a fairly complex 5-level hierarchy.
Users may query this hardware info. A user can specify nothing, the desired workgroup, the desired NUMA nodes, etc. down to level 4. In this case, the framework simply filters out the full data set and returns only what matches the input, so long as it complies with the hierarchy (i.e. the user doesn't say specify cores that don't appear under the specified processors).
Next, the user my specify ranges, as in "give me any 1 workgroup, any 1 numa node, and any 3 CPUs", for example. In this case, the framework should return the 3 CPUs with the lowest assignment. This is a filter & sort process.
Again, the user may specify his filter to any level.
The user could also simply specify nothing, which means the framework must return the hardware info, but sorted according to the load assignment at each level.
The process is always filter & sort, regardless of what the user specifies. The only difference is the user may specify a range, a count, or nothing.
To begin this process, I get the raw hardware data filtered according to what info is supplied by the user. This comes back as a flattened enumeration of object {L1, L2, L3, L4, L5) for each L5 object.
Next, I do the following:
IEnumerable<KeyValuePair<int, double>> wgSub;
IEnumerable<KeyValuePair<int, double>> nnSub;
IEnumerable<KeyValuePair<int, double>> cpSub;
IEnumerable<KeyValuePair<int, double>> coSub;
wgSub = (
from n in query
group n by n.L1.ID into g
select new KeyValuePair<int, double>(g.Key, g.Sum(n => n.L1.Assignment))
)
.OrderBy(o => o.Value);
nnSub = (
from n in query
group n by n.L2.ID into g
select new KeyValuePair<int, double>(g.Key, g.Sum(n => n.L2.Assignment))
)
.OrderBy(o => o.Value);
cpSub = (
from n in query
group n by n.L3.ID into g
select new KeyValuePair<int, double>(g.Key, g.Sum(n => n.L3.Assignment))
)
.OrderBy(o => o.Value);
coSub = (
from n in query
group n by n.L4.ID into g
select new KeyValuePair<int, double>(g.Key, g.Sum(n => n.L4.Assignment))
)
.OrderBy(o => o.Value);
query = (
from n in query
join wgj in wgSub on n.L1.ID equals wgj.Key
join nnj in nnSub on n.L2.ID equals nnj.Key
join cpj in cpSub on n.L3.ID equals cpj.Key
join coj in coSub on n.L4.ID equals coj.Key
select n
)
.OrderBy(o => o.L1.ID == wgSub.Key)
.ThenBy(o => o.L2.ID == nnSub.Key)
.ThenBy(o => o.L3.ID == cpSub.Key)
.ThenBy(o => o.L4.ID == coSub.Key);
Where I'm stuck is on the orderby (which will be 4 levels deep). I need to sort the input query by the ID in each sub-query, "thenby" the next, etc. What I wrote is not correct.
If the user specified a range or a count (both imply a quantity), I also need to implement a Take, possibly for each level.
Upvotes: 2
Views: 203
Reputation: 156594
I'm not super clear on what you're going for, but would it be something along these lines?
query = query
.OrderBy(n => wgSub.First(g => g.Key == n.L1.ID).Value)
.ThenBy(n => nnSub.First(g => g.Key == n.L1.ID).Value)
...
Upvotes: 1