有没有更有效的方式对这些词典进行排序

时间:2019-10-04 16:53:55

标签: c# sorting data-structures

因此,我查询了一个数据库以创建一个称为“活动”的集合,这些是具有相关问题和相关日期的调用。我需要返回前3个问题,询问活动日期是0-3个月,4-12个月还是一年以上。我创建了一个算法,但出于学习目的,我认为可能有更好的方法可以有效地对这些活动进行排序。这是我的代码


var activities = ctx.Activities.Where(a => a.SiteID == propID && a.ActivityTypeName == "Call" && a.ParcelData.Parcel_LetterTracking.LMailDate != null)       
    .Select(x => new 
    {                 
       callDate = x.DateTimeEntry,
       mailDate = x.Contact.OwnerContact.ParcelDatas.FirstOrDefault(a => a.OwnerContactID == x.Contact.OwnerContact.OOwnerID).Parcel_LetterTracking.LMailDate,
       question = x.FAQs.FirstOrDefault(a => a.ActivityID == x.ActivityID).FAQ_Library.FaqNum  + " - " + 
                  x.FAQs.FirstOrDefault(a => a.ActivityID == x.ActivityID).FAQ_Library.Question       
    }).AsEnumerable();


// create a dictionary of Key = the question and Value = the count of occurences in activities for each time frame. 
Dictionary<string, int> calls3month = new Dictionary<string, int>();
Dictionary<string, int> calls6month = new Dictionary<string, int>();
Dictionary<string, int> calls12month = new Dictionary<string, int>();
// counters for number of calls between each range
int numberOfCalls3Months = 0; 
int numberOfCalls4to6Months = 0;
int numberOfCalls12Months = 0;
foreach (var call in activities)
{
    // if calldate - maildate is 3 months, 4-12 months or 12+ months 
    TimeSpan deltaOfDates = call.callDate.Subtract((DateTime)call.mailDate); 
    if (deltaOfDates.Days < 91 && deltaOfDates.Days > 0)
    {                       
        if (calls3month.TryGetValue(call.question, out int count))
        {
            calls3month[call.question] = count + 1;
        }
        else {
            calls3month.Add(call.question, 1);
        }
        numberOfCalls3Months++; 
    }
    else if (deltaOfDates.Days < 365 && deltaOfDates.Days >= 91)
    {                     
        if (calls6month.TryGetValue(call.question, out int count))
        {
            calls6month[call.question] = count + 1;
        }
        else
        {
            calls6month.Add(call.question, 1);
        }
        numberOfCalls4to6Months++;
    }
    else if (deltaOfDates.Days >= 365)
    {
        if (calls12month.TryGetValue(call.question, out int count))
        {
            calls12month[call.question] = count + 1;
        }
        else
        {
            calls12month.Add(call.question, 1);
        }
        numberOfCalls12Months++;
    }
}
//grab top 3 questions asked. Key = the question, value = the frequency
var topCalls3month = calls3month.OrderByDescending(kvp => kvp.Value).Take(3).ToArray();
var topCalls6month = calls6month.OrderByDescending(kvp => kvp.Value).Take(3).ToArray();
var topCalls12month = calls12month.OrderByDescending(kvp => kvp.Value).Take(3).ToArray();

在通过活动收集枚举时对它们进行排序会更快吗?如果(dictionary.value位于前3名,则将其添加到列表的顶部) 我可以用什么策略来做到这一点?

最后,当我使用orderbyDescending时,我觉得这效率很低,并且应该对字典进行排序,使其脱离foreach循环/

1 个答案:

答案 0 :(得分:0)

您可以通过在结果字典上运行selection algorithm来避免排序(即OrderByDescending)。 Quickselect是一种O(n)算法,在渐近性方面比排序有效。您可能在线上可以找到很多实现。

使用选择算法实际上是否足够快而不必担心,这是另一个问题。即使您的数组包含一百万个项目,选择算法和排序之间的差异也可能不到一秒钟。您真的在乎是否能更快地获得答案吗?

相关问题