Using LINQ to GroupBy various properties and Sum length

Using LINQ to GroupBy various properties and Sum length

Anonymous
Not applicable
2,335 Views
6 Replies
Message 1 of 7

Using LINQ to GroupBy various properties and Sum length

Anonymous
Not applicable

Hello,

 

I am trying to use LINQ to organize all the Pipes in the model by System, Segment, then by Size and then sum the pipe length. I grab all the pipes in the model and get the System, Segment, Size and Length and put all that in to an IEnumerable. I then pass the IEnumerable through a LINQ operation to do GroupBy and Sum the Lengths of pipe for similar sized pipes with the same segment on the same system. Here is my code for the function that tries to do the GroupBy and Sum. I am not sure why I am getting an error that says "Cannot implicitly convert type 'double' to 'bool'" for the count operation so I have it commented out:

 

// Sum the length of pipe by system, segment, then size. Count pipes for each system/segment/size for checking
private IEnumerable<classPipesBySystem> sumPipeLength(List<pipesBySystem> theList)
{
    var sumPipeLengthList = theList.GroupBy(s => new { s.pipeSystem.Name, s.pipeSegment, s.pipeSize })
                                    .Select(g =>
                                    new classPipesBySystem
                                    {
                                        pipeSystemName = g.Key.Name,
                                        pipeSegment = g.Key.pipeSegment,
                                        pipeSize = g.Key.pipeSize,
                                        totalPipeLength = g.Sum(x => x.pipeLength),
                                        //pipeCount = g.Count(x => x.pipeLength)
                                    });


    return sumPipeLengthList;
}

 

Here is the call to the above function that passes in the IEnumerable. I was trying to iterate through the GroupBy Lists since it turns in to a Nested List but I get an error on the second foreach statement saying my classPipesBySystem class does not contain a public definition of GetEnumerator.

 

// Send the pipeSysInfo list to sumPipeLength to total the pipe length
IEnumerable<classPipesBySystem> sumPipeLengthInfo = sumPipeLength(pipeSysInfo);
foreach (var systemGroup in sumPipeLengthInfo)
{
    foreach (var segmentGroup in systemGroup) // Error about missing GetEnumerator definition in classPipesBySystem appears on this foreach
    {
        foreach (var sizeGroup in segmentGroup)
        {
        // Build a string listing each unique pipe size, segment, and system with total length
        }
    }
}

 

 

I'm not sure why it errors only on the second foreach and how I go about adding the GetEnumerator definition. Is the IEnumerable data type the correct type to use for the Nested List variable? Is there a better way to group and sum the pipe lengths for each size by segment and system other than using LINQ GroupBy?

 

Thanks,

Joe

0 Likes
2,336 Views
6 Replies
Replies (6)
Message 2 of 7

jeremytammik
Autodesk
Autodesk

Dear Joe,

 

Adressing this step by step and just guessing, I have a potential answer to your first question on why Count says "Cannot implicitly convert type 'double' to 'bool'". How about this explanation: Count expects a yes/no value to decide whether to include a given element in the count. You are providing a double value instead, the pipe length.

 

Do you want to count the number of pipes?

 

Count would be appropriate for that.

 

Do you want to sum up the total pipe length for all pipes?

 

That would be an aggregation.

 

To say anything more, I would have to copy and compile your code myself, I think.

 

Cheers,

 

Jeremy



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

0 Likes
Message 3 of 7

jeremytammik
Autodesk
Autodesk
0 Likes
Message 4 of 7

Anonymous
Not applicable

Hello Jeremy,

 

Thanks for the answer on question 1 concerning Count. It looks like I copied the same logic as the Sum function on the line above. Here is the corrected Count line

 

pipeCount = g.Count()

 The Count function is just in there for checking purposes so we can compare it to Count from a Pipe Schedule to make sure we are getting the right answer. I will likely hide Count and use it for diagnostic purposes only for the final plugin.

 

Ultimately the main purpose is to Sum Pipe Length based on the following unique Sorting:

1. Pipe system

     1.A. Pipe segment

          1.A.a. Pipe Size

 

For instance if I have the following data array of pipes with the following order of information:

 

Pipe System, Pipe Segment, Pipe Size, Pipe Length

HWS, Steel Sch40, 4", 10ft

HWS, Steel Sch40, 4", 20ft

HWS, Copper Type L, 1", 10ft

HWR, Steel Sch40, 4", 10ft

HWR, Steel Sch40, 4", 20ft

HWR, Copper Type L, 1", 10ft

 

I want the output to show the following:

HWS

     Steel Sch40

          4", Total Length = 30ft

     Copper Type L

          1", Total Length = 10ft

HWR

     Steel Sch40

          4", Total Length = 30ft

     Copper Type L

          1", Total Length = 10ft

 

In looking at this now I think I also need to combine duplicate lines of the same System, Segment, and Size. I think I can use the Distinct method to take care of that part.

 

Can you provide any input as how ot best use Aggregate for this situation? Any pointers would be helpful to get me started in the right direction as I like

 

Thanks,

Joe

0 Likes
Message 5 of 7

jeremytammik
Autodesk
Autodesk

Dear Joe,

 

Here are a couple of samples showing possible ways to use Aggregate:

 

 

I pointed to a couple of GroupBy demos yesterday.

 

Lacking the sample data, it is not easy to do more than that.

 

Good luck!

 

Cheers,

 

Jeremy



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

0 Likes
Message 6 of 7

Anonymous
Not applicable

Hello Jeremy,

 

Thanks for those links. The one on Data Grid View Population is especially helpful because I am trying to display all the pipes in a Data Grid View.

 

I am having trouble following how the data gets populated in the Data Grid. Why can't you simply set the DataSource of the Data Grid equal to the Data container?

 

I also found another post you did on populating a Data Grid View from an external file here:

http://thebuildingcoder.typepad.com/blog/2012/05/the-schedule-api-and-access-to-schedule-data.html

 

I used the code from your above post to setup the Data Grid View in code rather than a separate form and then I tried to set DataSource equal to my IEnumerable of data but I get a blank Data Grid when I run the command.

 

Thanks,

Joe

 

0 Likes
Message 7 of 7

Anonymous
Not applicable

Alright, I found the answer to the IEnumerable to DataTable here:

 

http://stackoverflow.com/questions/1253725/convert-ienumerable-to-datatable

 

I simplified my code to only grab Size and Length of Pipe for now until I get things working better. Once I get things running a little better I'll work on scaling things up.

 

Here is a shot of the Data Grid View I have so far. I noticed I am going to need to do some formatting cleanup but it is starting to look like something so it feels like a little win.

 

2015-03-12_11-30-37.png

 

Thanks for your help Jeremy! I am obviously not a programmer by trade so it feels like a fire hose of information is hitting me when I try to research online.

 

Cheers,

Joe