有没有更有效的方法将这些平面数据导入字典?

时间:2011-09-22 15:04:57

标签: c# .net linq-to-objects

我有以下代码:

public class Alert
{
    public string Alias { get; set; }
    public int ServiceHours { get; set; }
    public int TotalHoursDone { get; set; }
    public int UserId { get; set; }
    public int VehicleId { get; set; }
}

private static readonly List<Alert> AlertsToDo = new List<Alert>();

public void SomeFunction() {
    // creates a dictionary of user ids as the key with their alerts
    // (sorted by alias) as the value.
    // Just one loop needed and no awkward state logic.
    var alertsGrouped = AlertsToDo.Select(a => a.UserId)
                                  .Distinct()
                                  .ToDictionary(userId => userId,
                        userId => AlertsToDo.Where(a => a.UserId == userId)
                                            .OrderBy(a => a.Alias)
                                            .ToList());
}

所以,我有一个Alert对象列表。我的LINQ查询输出一个字典,其中的键是UserId,其值是按Alias排序的UserId的警报列表。

我很满意这个查询的独创性,但我想知道是否有更简单的方法吗?具体来说,我必须为每个键使用第二个查询来创建值List。纯粹出于兴趣,因为这对于手头的工作来说足够快。

2 个答案:

答案 0 :(得分:3)

使用Enumerable.GroupBy方法可以提高可读性。对于少量数据,您很可能看不到差异,而大量数据会改变性能。您的查询首先获取不同的值,然后过滤UserId上的项目。分组预先削减了这些步骤。要确定你需要描述一下。

以下是使用分组的查询:

var query = AlertsToDo.GroupBy(a => a.UserId)
                      .ToDictionary(g => g.Key,
                                    g => g.OrderBy(a => a.Alias).ToList());

答案 1 :(得分:0)

对于延迟感到抱歉,但正如这里承诺的那样是一些测试结果。

我测试过的代码:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    public class Alert
    {
        public string Alias { get; set; }
        public int ServiceHours { get; set; }
        public int TotalHoursDone { get; set; }
        public int UserId { get; set; }
        public int VehicleId { get; set; }
    }

    private static readonly List<Alert> AlertsToDo = new List<Alert>();

    private void button1_Click(object sender, EventArgs e)
    {
        var rng = new Random();

        var watch = new System.Diagnostics.Stopwatch();
        watch.Start();
        for (int i = 0; i < 1000000; i++)
        {
            int random = rng.Next();

            AlertsToDo.Add(new Alert
            {
                Alias = random.ToString(),
                UserId = random
            });
        }
        Console.WriteLine(@"Random generation: {0}", watch.ElapsedMilliseconds);

        watch = new System.Diagnostics.Stopwatch();
        watch.Start();
        var alertsGrouped = AlertsToDo.Select(a => a.UserId)
                              .Distinct()
                              .ToDictionary(userId => userId,
                    userId => AlertsToDo.Where(a => a.UserId == userId)
                                        .OrderBy(a => a.Alias)
                                        .ToList());
        watch.Stop();
        Console.WriteLine(@"Mine: {0}", watch.ElapsedMilliseconds);
        Console.WriteLine(alertsGrouped.Count);

        watch = new System.Diagnostics.Stopwatch();
        watch.Start();
        alertsGrouped = AlertsToDo.GroupBy(a => a.UserId)
                  .ToDictionary(g => g.Key,
                                g => g.OrderBy(a => a.Alias).ToList());
        watch.Stop();
        Console.WriteLine(@"Ahmad's: {0}", watch.ElapsedMilliseconds);
        Console.WriteLine(alertsGrouped.Count);
    }
}

输出:

随机生成:769

我的:32164861(超过8小时)

999798

艾哈迈德:4133

999798

不出所料,GroupBy更快,因为我的版本执行子查询,但只是看看有多快!

所以胜利者是:艾哈迈德,显然。