Reputation:
I have a list that contains the following class
public class File
{
public string Name{get;set;}
public int Year{get;set;}
public decimal Amount{get;set;}
}
My list could contain i.e List
Name="File 1" Year=2011 Amount=200
Name="File 2" Year=2012 Amount=400
Name="File 3" Year 2013 Amount=500
I would like the above list to be transform to contain the following values
Name="File 1" Year=2011 Amount=200
Name="File 1" Year=2012 Amount=0
Name="File 1" Year 2013 Amount=0
Name="File 2" Year=2011 Amount=400
Name="File 2" Year=2012 Amount=0
Name="File 2" Year 2013 Amount=0
Name="File 3" Year 2011 Amount=0
Name="File 3" Year=2012 Amount=0
Name="File 3" Year 2013 Amount=500
Note that the other items with an amount of 0 are automatically generated for the missing years
Upvotes: 1
Views: 179
Reputation: 1064234
foreach(var name in files.Select(x => x.Name).Distinct())
foreach(var year in files.Select(x => x.Year).Distinct())
{
var amount = (from file in files
where file.Name == name
&& file.Year == year
select (decimal?)file.Amount).SingleOrDefault() ?? 0M;
Console.WriteLine("Name={0}, Year={1}, Amount={2}",
name, year, amount);
}
Obviously it could be optimized - especially as a lookup for the amount via a dictionary; maybe:
var amounts = files.ToDictionary(
file => new {file.Name,file.Year}, file => file.Amount);
foreach(var name in files.Select(file => file.Name).Distinct())
foreach(var year in files.Select(file => file.Year).Distinct())
{
decimal amount;
if(!amounts.TryGetValue(new {file.Name,file.Year}, out amount) amount = 0M;
Console.WriteLine("Name={0}, Year={1}, Amount={2}",
name, year, amount);
}
Upvotes: 3
Reputation: 6499
For the default value, you can add a constructor :
public class File
{
public File() { this.Amout = 0; }
public string Name{get;set;}
public int Year{get;set;}
public decimal Amount{get;set;}
}
For the OrderBy, you can look on this example
Upvotes: 0