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

发布于 2024-12-06 03:41:10 字数 1097 浏览 0 评论 0原文

我有以下代码:

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());
}

因此,我有一个警报对象列表。我的 LINQ 查询输出一个字典,其键是 UserId,其值是按别名排序的该 UserId 的警报列表。

我对这个查询的独创性感到非常满意,但我想知道是否有更简单的方法来做到这一点?具体来说,我必须对每个键使用第二个查询来创建值列表。纯粹出于兴趣而询问,因为这对于手头的工作来说足够快了。

I have the following code:

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());
}

So, I have a list of Alert objects. My LINQ query outputs a Dictionary the key of which is the UserId and the value of which is a List of Alerts for that UserId sorted by Alias.

I'm happy enough with the ingenuity of this query but am wondering if there's an easier way to do it? Specifically, I'm having to use a second query for every key to create the value List. Asking purely out of interest as this is fast enough for the job in hand.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

凉城已无爱 2024-12-13 03:41:10

有一种更短、更具可读性的方法,使用 Enumerable.GroupBy 方法。对于少量数据,您很可能不会看到差异,而大量数据会改变性能。您的查询首先获取不同的值,然后过滤 UserId 上的项目。这种分组减少了前期的这些步骤。要确定,您需要进行分析。

这是使用分组的查询:

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

There's a shorter approach that is more readable, using the Enumerable.GroupBy method. For a small amount of data you most likely won't see a difference, whereas a large amount of data would change the performance. Your query first gets the distinct values, then filters items on UserId. The grouping cuts down on those steps upfront. To know for sure you would need to profile.

Here's the query using grouping:

var query = AlertsToDo.GroupBy(a => a.UserId)
                      .ToDictionary(g => g.Key,
                                    g => g.OrderBy(a => a.Alias).ToList());
謌踐踏愛綪 2024-12-13 03:41:10

抱歉延迟了,但正如所承诺的,这里有一些测试结果。

我测试的代码:

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 更快,因为我的版本执行子查询,但看看快了多少!

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

Sorry about the delay, but as promised here are some test results.

The code I tested with:

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);
    }
}

And the output:

Random generation: 769

Mine: 32164861 (over 8 hours)

999798

Ahmad's: 4133

999798

Unsurprisingly the GroupBy is quicker as my version performs a subquery, but just look at how much quicker!

So the winner is: Ahmad, obviously.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文