检查List <t>以查找日期的最快方法</t>

时间:2010-04-10 13:40:52

标签: c# generics .net-2.0 generic-list

我有一个机器已经处理的日期列表,但它没有包含机器停机的日期。我需要创建一个工作日但没有工作的列表。我不确定这样做的最好方法。我已经开始通过递增范围的所有日期并通过每次迭代整个列表来检查日期是否在列表中。我正在寻找一种更有效的方法来查找日期。

class machineday
{
 datetime WorkingDay;
}

class machinedaycollection : List<machineday>
{
public List<TimeCatEvent> GetAllByCat(string cat)
{
  _CategoryCode = cat;


  List<machineday> li = this.FindAll(delegate(machinedaydummy) { return true; });
  li.Sort(sortDate);
  return li;
}

int sortDate(machinedayevent1, machinedayevent2)
{
  int returnValue = -1;
  if (event2.date < event1.date)
  {
    returnValue = 0;
  }
  else if (event2.date == event1.date)
  {
    //descending
    returnValue = event1.date.CompareTo(event2.date);
  }
  return returnValue;
}
}

5 个答案:

答案 0 :(得分:6)

对日期进行排序并平行迭代结果列表以递增计数器。只要计数器与当前列表元素不匹配,您就会在列表中找到一个日期。

List<DateTime> days = ...;
days.Sort();
DateTime dt = days[0].Date;
for (int i = 0; i < days.Length; dt = dt.AddDays(1))
{
    if (dt == days[i].Date)
    {
        Console.WriteLine("Worked: {0}", dt);
        i++;
    }
    else
    {
        Console.WriteLine("Not Worked: {0}", dt);
    }
}

(这假设列表中没有重复日期。)

答案 1 :(得分:3)

使用LINQ的Enumerable.Except扩展方法构建有效日期列表并从中减去机器日集合。像这样:

IEnumerable<DateTime> dates = get_candidate_dates();
var holidays = dates.Except(machinedays.Select(m => m.WorkingDay));

get_candidate_dates()方法甚至可以是一个迭代器,它可以动态生成范围内的所有日期,而不是预先存储的所有日期列表。

Enumerable的方法相当聪明,通常在性能方面做得不错,但如果你想要最快的算法,那将取决于你计划如何使用结果。

答案 2 :(得分:3)

对不起老兄,但我不太喜欢你的解决方案。 我想你应该用你的日期创建一个HashTable。您可以通过仅在工作日进行一次处理来完成此操作。

然后,如果日期存在与否,您可以在哈希表中查询整个天数以及查询的每一天,使用

myHashTable.ContainsKey(day); // this is efficient

简单,优雅,快速。

我认为你的解决方案使用了一个指数时间,这个是直线或对数的(这实际上是一件好事)。

答案 3 :(得分:0)

假设列表已排序且机器在大多数时间处于“工作”状态,您可以通过按月对日期进行分组并跳过两者之间的日期来避免遍历所有日期。这样的事情(你需要清理):

int chunksize = 60; // adjust depending on data
machineday currentDay = myMachinedaycollection[0];

for (int i = 0; i < myMachinedaycollection.Count; i += chunksize)  
{  
    if (currentDay.WorkingDay.AddDays(chunksize) != myMachinedaycollection[i + chunksize].WorkingDay)  
    {
        // write code to iterate through current chunk and get all the non-working days  
    }
    currentDay = myMachinedaycollection[i + chunksize];  
}  

答案 4 :(得分:0)

我怀疑你想要一份工作日和无效工作的清单。

您的问题标题表明您想知道系统是否在特定日期启动。计算%正常运行时间似乎也是合理的。这些都不需要在区间内建立所有时间瞬间的列表。

对服务时间进行排序。对于第一个问题,请将BinarySearch作为您关注的日期,并检查前面的条目是否正在使系统脱离维护或重新投入使用。对于%正常运行时间,选择(向下维护,服务恢复)成对,使用减法查找维护的持续时间,添加它们。然后使用减法来查找总间隔的长度。

如果您的问题实际上并不意味着您正在跟踪维护间隔(或等效的使用间隔),那么您可以忽略此答案。