【发布时间】:2019-10-04 16:53:55
【问题描述】:
所以我查询了一个数据库来创建一个名为“活动”的集合,这些调用具有相关的问题和相关的日期。如果活动日期是 0-3 个月、4-12 个月或超过一年,我需要返回前 3 个问题。我创建了一个算法,但出于学习目的,我认为可能有更好的方法来有效地对这些活动进行分类。这是我的代码
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();
在我列举活动集合时对这些进行排序会更快吗? if(dictionary.value is in top 3 将其添加到列表顶部) 我可以使用什么策略来做到这一点?
最后,当我使用 orderbyDescending 时,我觉得这效率低下,应该从 foreach 循环中对字典进行排序/
【问题讨论】:
-
不看任何细节,我认为你可以做 Parallel.For(0, activities.Length, (i) => { /*Do checks...*/ });利用 ConcurrentDictionary docs.microsoft.com/en-us/dotnet/api/…
-
不会影响性能,但您可以简化块以增加计数
calls6month[call.question] = calls6month.GetValueOrDefault() + 1; -
有时最好通过数据库查询来完成。
-
@TerryTyson 我考虑过这一点,但我需要不同列表中的不同日期。有没有办法可以在一个查询中组织它们(而不是 3 个查询)?如果我必须使用 .Where(日期时间在 3 个月/6 个月/12 个月内) 进行 3 次查询,那效率会不会降低?
-
除非你有数百万条记录,否则这个函数的性能瓶颈将是一个 sql 查询。代码可读且干净,可以保持原样,直到您开始出现明显的性能问题。
标签: c# sorting data-structures