繁体   English   中英

我如何在 linq 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();

还可以为每个列表成员使用更动态的对象,例如DataTableDictionaryExpandoObject ,甚至可以在运行时创建匿名对象,尽管在大多数情况下这是有问题的价值,因为您可以' t 轻松访问其字段。 但是,如果您不知道Day值是如何可能的,并且想要处理不同的数字,则必须使用这些值之一或用某种类型的集合代替 day 字段(例如数组、列表或字典) )。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM