![](/img/trans.png)
[英]How do I create a list object that contains a list of another object type using from within a query using linq and c#
[英]how do i pivot list of object and create new list in linq c#?
我有一份員工每天工作時間數據的列表。 我想透視日期和小時數據,並創建一個新的對象列表,其中包含員工姓名,以及以相應小時數為值的一系列天數。
我的清單看起來像
List<EmployeeHour> employeeHours = new List<EmployeeHour>
{
new EmployeeHour{Id = 1, EmployeeName = "Emp1", Day = 1, Hours = 6},
new EmployeeHour{Id = 1, EmployeeName = "Emp1", Day = 2, Hours = 8},
new EmployeeHour{Id = 2, EmployeeName = "Emp2", Day = 1, Hours = 6},
new EmployeeHour{Id = 2, EmployeeName = "Emp2", Day = 2, Hours = 8}
};
我想創建新的對象列表,其中的時間類似於
new {
Id = 1,
EmplyeeName = Emp1,
Day1 = 6,
Day2 = 8
},
new {
Id = 2,
EmplyeeName = Emp2,
Day1 = 6,
Day2 = 8
}
我就是這樣做的。 有更好的解決方案嗎?
dynamic d = new
{
Employee = group.FirstOrDefault().EmployeeName,
Day1 = group.FirstOrDefault(g => g.DayNumber == 1)?.HoursPerDay,
Day2 = group.FirstOrDefault(g => g.DayNumber == 2)?.HoursPerDay,
Day3 = group.FirstOrDefault(g => g.DayNumber == 3)?.HoursPerDay,
Day4 = group.FirstOrDefault(g => g.DayNumber == 4)?.HoursPerDay,
Day5 = group.FirstOrDefault(g => g.DayNumber == 5)?.HoursPerDay,
Day6 = group.FirstOrDefault(g => g.DayNumber == 6)?.HoursPerDay,
Day7 = group.FirstOrDefault(g => g.DayNumber == 7)?.HoursPerDay
};
list.Add(d);
C# 是一種強類型語言,因此類屬性的可變性是有限的。 似乎更適合您的是Dictionary<string, object>
:
var dictionaries = employeeHours.Select(x => new {x.Id, x.EmployeeName})
.Distinct()
.Select(x => new Dictionary<string, object>()
{
{"Id", x.Id},
{"EmployeeName", x.EmployeeName}
})
.ToList();
foreach (var dict in dictionaries)
{
var id = (int)dict["Id"];
foreach (var dh in employeeHours.Where(x => x.Id == id))
{
if (!dict.ContainsKey("Day" + dh.Day))
{
dict["Day" + dh.Day] = dh.Hours;
}
}
}
這段代碼會給你一個可變長度的字典,當它使用 JSON 轉換時,它應該為你提供數據表中所需的數據結構。
如果您希望結果是靜態類型的匿名(或定義的類)對象,則需要執行類似於您正在執行的操作。
我將使用從每個組轉換而來的增強型字典類型,以便更輕松地提取值:
//***
// Enhanced Dictionary that returns default(TValue) for missing values
//***
public class NullDictionary<TKey, TValue> : Dictionary<TKey, TValue> {
public NullDictionary(IDictionary<TKey, TValue> d) : base() {
foreach (var kvp in d)
Add(kvp.Key, kvp.Value);
}
public NullDictionary() : base() { }
public new TValue this[TKey key]
{
get
{
TryGetValue(key, out var val);
return val;
}
set
{
base[key] = value;
}
}
}
使用擴展方法使創建變得容易:
public static class DictExt {
public static NullDictionary<TKey, TValue> ToNullDictionary<T, TKey, TValue>(this IEnumerable<T> src, Func<T, TKey> keyFn, Func<T, TValue> valFn) {
var nd = new NullDictionary<TKey, TValue>();
foreach (var s in src)
nd.Add(keyFn(s), valFn(s));
return nd;
}
}
現在您可以使用GroupBy
透視數據並提取匿名對象:
var ans = employeeHours.GroupBy(eh => new { eh.Id, eh.EmployeeName }, eh => new { Day = $"Day{eh.Day}", eh.Hours })
.Select(pg => {
var pd = pg.ToNullDictionary(p => p.Day, p => (int?)p.Hours);
return new {
pg.Key.Id,
pg.Key.EmployeeName,
Day1 = pd["Day1"],
Day2 = pd["Day2"],
Day3 = pd["Day3"],
Day4 = pd["Day4"],
Day5 = pd["Day5"],
Day6 = pd["Day6"],
Day7 = pd["Day7"],
};
})
.ToList();
還可以為每個列表成員使用更動態的對象,例如DataTable
或Dictionary
或ExpandoObject
,甚至可以在運行時創建匿名對象,盡管在大多數情況下這是有問題的價值,因為您可以' t 輕松訪問其字段。 但是,如果您不知道Day
值是如何可能的,並且想要處理不同的數字,則必須使用這些值之一或用某種類型的集合代替 day 字段(例如數組、列表或字典) )。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.