我有以下用数据填充的类
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; } }
我有一个IEnumerable结果,其中包含如下数据:
IEnumerable<cntryData> result USA United States 2000 12 2001 22 2004 32 CAN Canada 2001 29 2003 22 2004 24
我想使用LINQ评估“result”对象以获得以下结果:
2000 USA 12 CAN null 2001 USA 22 CAN 29 2003 USA null CAN 22 2004 USA 32 CAN 24
如果结果有更多的国家(比如中国的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
可以使用LINQ完成吗?谢谢.
解决方法
我发现很难在这个问题上找到一个干净的答案,我仍然不太满意,所以欢迎反馈:
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; }
pivot每年将包含一个项目.每个国家/地区中的每个项目都包含一个项目.
如果要将每一行格式化为字符串,可以执行以下操作:
pivot.Select(g => string.Format("{0} {1}",g.Key,string.Join("\t",g.Select(x => string.Format("{0} {1}",x.Country,x.Value)))));