使用Linq加入多个IEnumerable <>

hss*_*hss 6 c# linq

我有以下用数据填充的类

public class cntrydata
{
    public string countryid { get; set; }
    public string countryname { get; set; }

    public IEnumerable<Data> data { get; set; }

}
public class Data
{
        public int year { get; set; }
        public float value { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我有一个IEnumerable结果,其中包含如下数据:

IEnumerable<cntryData> result

USA
United States
   2000 12
   2001 22
   2004 32

CAN
Canada
   2001 29
   2003 22
   2004 24
Run Code Online (Sandbox Code Playgroud)

我想使用LINQ评估"result"对象以获得以下结果:

2000 USA 12   CAN null
2001 USA 22   CAN 29
2003 USA null CAN 22
2004 USA 32   CAN 24
Run Code Online (Sandbox Code Playgroud)

如果结果有更多的国家(比如中国的1995年价值为12)那么结果应该是这样的:

1995 USA null   CAN null CHN 12
2000 USA 12     CAN null CHN null
2001 USA 22     CAN 29   CHN null
2003 USA null   CAN 22   CHN null
2004 USA 32     CAN 24   CHN null
Run Code Online (Sandbox Code Playgroud)

可以使用LINQ完成吗?谢谢.

Dan*_*rth 4

我发现在这个问题上很难给出一个明确的答案,而且我仍然不太满意,所以欢迎反馈:

var countries = result.Select(x => x.countryid).Distinct();
var years = result.SelectMany(x => x.data).Select(x => x.year).Distinct();
var data = result.SelectMany(x => x.data
                                   .Select(y => new { Country = x.countryid,
                                                      Data = y }))
                 .ToDictionary(x => Tuple.Create(x.Country, x.Data.year),
                               x => x.Data.value);   

var pivot = (from c in countries
             from y in years
             select new { Country = c, Year = y, Value = GetValue(c, y, data) })
            .GroupBy(x => x.Year)
            .OrderBy(x => x.Key);



public float? GetValue(string country, int year,
                       IDictionary<Tuple<string, int>, float> data)
{
    float result;
    if(!data.TryGetValue(Tuple.Create(country, year), out result))
        return null;
    return result;
}
Run Code Online (Sandbox Code Playgroud)

pivot每年将包含一个项目。其中每个项目将包含每个国家/地区的一个项目。

如果你想将每一行格式化为字符串,你可以这样做:

pivot.Select(g => string.Format("{0} {1}", g.Key, string.Join("\t", g.Select(x => string.Format("{0} {1}", x.Country, x.Value)))));
Run Code Online (Sandbox Code Playgroud)