0

My fledgling programming skills have hit a wall. I could get this working, but the code stinks and I'm convinced there must be a more efficient way I just don't know it yet.

I have a web service that accepts the name of a data property as a parameter. Part of the method for handling the request is to go away and get me a load of data for the specified data property. In my case, it says go and get me the current year's target and actual for the 'electricity usage' property in the database.

In my code this is just like:

var data = rSvc.getDashboardPayload(worklocation, property, year);

The is then delivered as a JSON payload that just says (snipped example):

0:  {
month: 1
monthName: "Jan"
currentYearTarget: 100
currentYearActual: 90
}

However, a change has come up that we need to produce a chart that is actually just a total of 4 measures in the database. For example: "Hazardous Waste" is the total of non-metallic waste, plus the total of metallic waste, plus the total of incinerated waste... and so on. You get the picture.

So in my code I can get a payload for each measure like this:

var shwl = rSvc.getDashboardPayload(worklocation, propName, year);
var shwi = rSvc.getDashboardPayload(worklocation, propName, year);
var shmwr = rSvc.getDashboardPayload(worklocation, propName, year);
var shnmwr = rSvc.getDashboardPayload(worklocation, propName, year);

Then I can create a new list that will be my output:

var merged = new List<WLDChartsPayload>(12);

Then I can loop through 12 months and go and total up each measure in turn.

for (short i = 1; i < 13; i++)
 {
   var m = new WLDChartsPayload();

   m.currentYearActual = shwl.Where(x => x.currentYearActual.HasValue && x.month == i).FirstOrDefault().currentYearActual;
   m.currentYearActual += shwi.Where(x => x.currentYearActual.HasValue && x.month == i).FirstOrDefault().currentYearActual;
   m.currentYearActual += shmwr.Where(x => x.currentYearActual.HasValue && x.month == i).FirstOrDefault().currentYearActual;
   m.currentYearActual += shnmwr.Where(x => x.currentYearActual.HasValue && x.month == i).FirstOrDefault().currentYearActual;

   m.currentYearTarget = shwl.Where(x => x.currentYearTarget.HasValue && x.month == i).FirstOrDefault().currentYearTarget;
   m.currentYearTarget += shwi.Where(x => x.currentYearTarget.HasValue && x.month == i).FirstOrDefault().currentYearTarget;
   m.currentYearTarget += shmwr.Where(x => x.currentYearTarget.HasValue && x.month == i).FirstOrDefault().currentYearTarget;
   m.currentYearTarget += shnmwr.Where(x => x.currentYearTarget.HasValue && x.month == i).FirstOrDefault().currentYearTarget;

   merged.Add(m);
 }

Then I return the merged list.

But this just feels wrong. I have 10 data points in the payload. The code is getting longer and more repetitive.

But, question is, how else can I "totalise and condense" the values from all four of my arrays into a single array?

5
  • 1
    Loops can be nested into loops, and in this case they should be. Instead of enumerating all the different data sources, store their values into a collection and then iterate over that inside your existing loop. Commented Nov 27, 2014 at 14:24
  • 1
    I guess this belongs rather to stackoverflow...
    – dagnelies
    Commented Nov 27, 2014 at 14:27
  • Thanks KilianFoth, I never thought of it like that. Sorry arnaud I did ponder putting it on SO but thought here was more appropriate because I was more interested in the conceptual answer. Still learning.
    – Mike Rouse
    Commented Nov 27, 2014 at 14:30
  • 2
    On a totally unrelated note, you may wish to reconsider the variable names 'shwl', 'shwi', etc. Always code as if the person who ends up maintaining your code is a violent psychopath who knows where you live Commented Nov 28, 2014 at 20:40
  • Totally agree. I start with these short names and then use Visual Studio's features to quickly rename them to something more meaningful once I'm happy with the method.
    – Mike Rouse
    Commented Nov 28, 2014 at 22:37

1 Answer 1

1

First, I'd recommend away from names like shwl. Use a real phrase that actually describes what the data contains. C# is deliberately wordy in its API and you should follow suit.

In regards to the actual problem, it is hard to follow your request, but there are a few obvious things you can do:

First you have several lists, so make them into one list:

var myLists = new List<WhatEverType>() 
                {
                   rSvc.getDashboardPayload(worklocation, propName, year),
                   rSvc.getDashboardPayload(worklocation, propName, year),
                   rSvc.getDashboardPayload(worklocation, propName, year),
                   rSvc.getDashboardPayload(worklocation, propName, year),
                };

Now you can process them as a group, so your loop body is:

for (short i = 1; i < 13; i++)
{
   var m = new WLDChartsPayload();
   m.currentYearActual = myLists.Sum(list =>item.FirstOrDefault(x => x.currentYearActual.HasValue && x.month == i).currentYearActual);
   m.currentYearTarget= myLists.Sum(list =>item.FirstOrDefault(x => x.currentYearTarget.HasValue && x.month == i).currentYearTarget);
   merged.Add(m);
}

If the Linq is too complicated for your liking they you can unroll it into a foreach loop (replacing the for() loop body with...):

m.currentYearActual = m.currentYearTarget = 0;
foreach(var list in myLists)
{
   m.currentYearActual += itemlist.FirstOrDefault(x => x.currentYearActual.HasValue && x.month == i).currentYearActual);
   m.currentYearTarget += itemlist.FirstOrDefault(x => x.currentYearTarget .HasValue && x.month == i).currentYearTarget );
}
merged.Add(m);

I'm not exactly clear on all the details of your original code -- you don't supply enough detail, so I haven't compiled these ideas, however, something along these lines will address your basic concerns. Adding more lists keeps the code the same but just adds a new line to the myLists initializer.

1
  • Thanks - this was exactly the kind of thing I was looking for. Specifically the idea of the one list, and also the Linq method for handling the properties once inside the code. By having one list I can then do the Sum successfully. Also take on board your naming point.
    – Mike Rouse
    Commented Nov 30, 2014 at 18:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.