使用Linq在c#list中生成缺少的列表值

时间:2013-03-08 11:37:50

标签: c# linq

我有一个包含以下类的列表

    public class File
{
    public string Name{get;set;}
    public int Year{get;set;}
    public decimal Amount{get;set;}

}

我的列表可以包含列表

Name="File 1" Year=2011 Amount=200
Name="File 2" Year=2012 Amount=400
Name="File 3" Year 2013 Amount=500

我希望将上面的列表转换为包含以下值

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

请注意,缺少年份会自动生成金额为0的其他项目

2 个答案:

答案 0 :(得分:3)

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);
}

显然它可以被优化 - 特别是通过字典查找金额;也许:

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);
}

答案 1 :(得分:0)

对于默认值,您可以添加构造函数:

public class File
{
    public File() { this.Amout = 0; }

    public string Name{get;set;}
    public int Year{get;set;}
    public decimal Amount{get;set;}
}

对于OrderBy,您可以查看this example