Home > other >  List of objects, add properties together based of another property
List of objects, add properties together based of another property

Time:06-30

I have a List that contains 2 properties per object. The properties are as follows:

string Project;
double Value;

So in any given case we might have a List of 5 objects, where 3 of them have a Project property called "Test" and the other 2 objects have a Project Property called "Others", but none of the 5 objects have the same "Value".

{
    Project = "Test" Value = 1, 
    Project = "Test" Value = 5, 
    Project = "Test" Value = 25,
    Project = "Others" Value = 89, 
    Project = "Others" Value = 151
}

Okay, I get a lot of data from a Database (I "Query" it out into a List of objects), then I take the specific properties I need from that List and add to my own List as follows.

public class Data
{
public string Project {get; set;}
public double Value {get; set;}
}
public List<Data> dataList = new List<Data>();

foreach(var item in DatabaseList)
{
Data newData = new Data(
data.Project = item.Project;
data.Value = item.Project;
dataList.Add(newData);
}

This gives me my list of data that I somehow need to combine based on the property in "Project"

But I have a hard time figuring out how to seperate them from one another, my first thought was to find "Unique" "Projects" and adding that to a new List called "counter", to then loop through that list based of the "Project" property, so something like this:

List<Data> counter = dataList.GroupBy(x => x.Project).Select(First()).ToList();

foreach(var item in counter)
{
Data finalItem = new Data();
   foreach (var item2 in dataList)
   {
       if(item.Project == item2.Project)
       {
        finalItem.Project = item2.Project;
        finalItem.Value  = item2.Value;
        finalList.Add(finalItem);
       }
   }
}

So I already know that the above is so messy its crazy, and its also not going to work, but this was the angle I was trying to take, I was also thinking whether I could maybe make use of Dictionary, but I feel like there is probably a super simple solution to something like this.

CodePudding user response:

You can use the following code to compute the total Value for objects with Project="Test" :

double TestsValue = my_list.Where(o=>o.Project=="Test").Sum(t=>t.Value);

and do the same for "Others".

CodePudding user response:

Assuming you're happy to return an IEnumerable of Data, you can do this:

var projects = dataList.GroupBy(p => p.Project)
                       .Select(grp => 
                           new Data 
                           { 
                               Project = grp.First().Project, 
                               Value = grp.Sum(pr => pr.Value) 
                           });

CodePudding user response:

I think your initial thoughts regarding making use of a dictionary are good. Your use of .GroupBy() is a first step to create that dictionary, where the project name is the dictionary Key and the sum of values for that project is the dictionary Value.

You already seem to be familiar with the System.Linq namespace. The extension method .ToDictionary() exists in the same namespace, and can be used to define the Key and Value predicate for each KeyValuePair (KVP) in the dictionary as follows:

.ToDictionary(
    <predicate for Key>,
    <predicate for Value>
);

The dictionary may be created by utilizing .ToDictionary() directly after .GroupBy(), as follows:

Dictionary<string, double> dataDictionary = dataList
    .GroupBy(item => item.Project)
    .ToDictionary(
        itemsByProject => itemsByProject.Key,
        itemsByProject => itemsByProject.Sum(item => item.Value));

Example fiddle here.

  • Related