如何根据C#中的Datetime键获取列表的子集?
我有一个元素列表,描述在某个时间发生的事件,时间被表示为对象上的Datetime属性“StartTime”。现在,我希望提取这些事件的一个子集,其中包含放置在两个DateTime实例a、B之间的间隔/中的元素,以便StartTime>=a&&StartTime如果可能,我会将实例保留在一个数组中,按StartTime排序,然后调用BinarySearch来确定数组中边界结束处的索引 然后,考虑到这一点,您可以轻松快速地访问基于日期范围的子集 我已经建立了一个通用类,它也可以帮助您:如何根据C#中的Datetime键获取列表的子集?,c#,sorting,list,C#,Sorting,List,我有一个元素列表,描述在某个时间发生的事件,时间被表示为对象上的Datetime属性“StartTime”。现在,我希望提取这些事件的一个子集,其中包含放置在两个DateTime实例a、B之间的间隔/中的元素,以便StartTime>=a&&StartTime如果可能,我会将实例保留在一个数组中,按StartTime排序,然后调用BinarySearch来确定数组中边界结束处的索引 然后,考虑到这一点,您可以轻松快速地访问基于日期范围的子集 我已经建立了一个通用类,它也可以帮助您: public
public class BinarySearcher<T>
{
// Possibly passed to the call to BinarySort.
private class ComparisonComparer : Comparer<T>
{
Comparison<T> comparison;
internal static IComparer<T> Create(Comparison<T> comparison)
{
// If comparison is null, return the default comparer for T.
if (comparison == null)
{
// Return the default.
return Comparer<T>.Default;
}
// Return a new implementation.
return new ComparisonComparer(comparison);
}
private ComparisonComparer(Comparison<T> comparison)
{
this.comparison = comparison;
}
public override int Compare(T x, T y)
{
return comparison(x, y);
}
}
// The elements.
T[] elements;
// The IComparable implementation.
IComparer<T> comparer;
// Do not assume sorting.
public BinarySearcher(IEnumerable<T> elements) :
this(elements, false, (IComparer<T>) null) { }
// Use default comparer.
public BinarySearcher(IEnumerable<T> elements, bool sorted) :
this(elements, sorted, (IComparer<T>) null) { }
// Assume no sorting.
public BinarySearcher(IEnumerable<T> elements,
Comparison<T> comparer) :
this(elements, false,
ComparisonComparer.Create(comparer)) { }
// Convert to IComparable<T>.
public BinarySearcher(IEnumerable<T> elements, bool sorted,
Comparison<T> comparer) :
this(elements, sorted,
ComparisonComparer.Create(comparer)) { }
// No sorting.
public BinarySearcher(IEnumerable<T> elements,
IComparer<T> comparer) :
this(elements, false, comparer) { }
// Convert to array.
public BinarySearcher(IEnumerable<T> elements, bool sorted,
IComparer<T> comparer) :
this(elements.ToArray(), sorted, comparer) { }
// Assume no sorting.
public BinarySearcher(T[] elements) : this(elements, false) { }
// Pass null for default comparer.
public BinarySearcher(T[] elements, bool sorted) :
this(elements, sorted, (IComparer<T>) null) { }
// Assume not sorted.
public BinarySearcher(T[] elements, Comparison<T> comparer) :
this(elements, false, ComparisonComparer.Create(comparer)) { }
// Create IComparable<T> from Comparable<T>.
public BinarySearcher(T[] elements, bool sorted,
Comparison<T> comparer) :
this(elements, sorted, ComparisonComparer.Create(comparer)) { }
// Assume the elements are not sorted.
public BinarySearcher(T[] elements, IComparer<T> comparer) :
this(elements, false, comparer) { }
public BinarySearcher(T[] elements, bool sorted,
IComparer<T> comparer)
{
// If the comparer is null, create the default one.
if (comparer == null)
{
// Set to the default one.
comparer = Comparer<T>.Default;
}
// Set the comparer.
this.comparer = comparer;
// Set the elements. If they are sorted already, don't bother,
// otherwise, sort.
if (!sorted)
{
// Sort.
Array.Sort(elements, this.comparer);
}
// Set the elements.
this.elements = elements;
}
public IEnumerable<T> Between(T from, T to)
{
// Find the index for the beginning.
int index = Array.BinarySearch(this.elements, from, comparer);
// Was the item found?
bool found = (index >= 0);
// If the item was not found, take the bitwise
// compliment to find out where it would be.
if (!found)
{
// Take the bitwise compliment.
index = ~index;
}
// If the item was found, cycle backwards from
// the index while there are elements that are the same.
if (found)
{
// Cycle backwards.
for (; index >= 0 &&
comparer.Compare(from, elements[index]) == 0;
--index) ;
// Add one to the index, since this is on the element
// that didn't match the comparison.
index++;
}
// Go forward now.
for ( ; index < elements.Length; index++)
{
// Return while the comparison is true.
if (comparer.Compare(elements[index], to) <= 0)
{
// Return the element.
yield return elements[index];
}
else
{
// Break
yield break;
}
}
}
}
您可以执行以下操作:
// Create tasks.
Task[] tasks =
{
new Task() { Name = "Task 1", StartTime = new DateTime(2009, 02, 18) },
new Task() { Name = "Task 2", StartTime = new DateTime(2009, 02, 16) },
new Task() { Name = "Task 3", StartTime = new DateTime(2009, 02, 12) },
new Task() { Name = "Task 4", StartTime = new DateTime(2009, 02, 11) },
new Task() { Name = "Task 5", StartTime = new DateTime(2009, 02, 10) },
new Task() { Name = "Task 6", StartTime = new DateTime(2009, 02, 01) },
new Task() { Name = "Task 7", StartTime = new DateTime(2009, 02, 09) }
};
// Now create the indexer.
BinarySearcher<Task> searcher = new BinarySearcher<Task>(tasks,
(x, y) => Comparer<DateTime>.Default.Compare(x.StartTime, y.StartTime));
foreach (Task t in searcher.Between(
new Task() { StartTime = new DateTime(2009, 02, 13) },
new Task() { StartTime = new DateTime(2009, 02, 10) }))
{
// Write.
Console.WriteLine(t);
}
//创建任务。
任务[]任务=
{
新任务(){Name=“Task 1”,StartTime=new DateTime(2009,02,18)},
新任务(){Name=“Task 2”,StartTime=new DateTime(2009,02,16)},
新任务(){Name=“Task 3”,StartTime=new DateTime(2009,02,12)},
新任务(){Name=“Task 4”,StartTime=new DateTime(2009,02,11)},
新任务(){Name=“Task 5”,StartTime=new DateTime(2009,02,10)},
新任务(){Name=“Task 6”,StartTime=new DateTime(2009,02,01)},
新任务(){Name=“Task 7”,StartTime=new DateTime(2009,02,09)}
};
//现在创建索引器。
BinarySearcher search=新的BinarySearcher(任务,
(x,y)=>Comparer.Default.Compare(x.StartTime,y.StartTime));
foreach(searcher.Between中的任务t(
新任务(){StartTime=new DateTime(2009,02,13)},
新任务(){StartTime=newdatetime(2009,02,10}))
{
//写。
控制台写入线(t);
}
是否签出数组。使用自定义谓词查找?啊,谢谢。我不知道BinarySearch(..)在没有找到精确匹配时返回了“最近的索引”。据我所知,在SortedList上没有直接的搜索方法。只需要弄清楚是否可以直接访问SortedList的值数组,以重用插入逻辑。
// Create tasks.
Task[] tasks =
{
new Task() { Name = "Task 1", StartTime = new DateTime(2009, 02, 18) },
new Task() { Name = "Task 2", StartTime = new DateTime(2009, 02, 16) },
new Task() { Name = "Task 3", StartTime = new DateTime(2009, 02, 12) },
new Task() { Name = "Task 4", StartTime = new DateTime(2009, 02, 11) },
new Task() { Name = "Task 5", StartTime = new DateTime(2009, 02, 10) },
new Task() { Name = "Task 6", StartTime = new DateTime(2009, 02, 01) },
new Task() { Name = "Task 7", StartTime = new DateTime(2009, 02, 09) }
};
// Now create the indexer.
BinarySearcher<Task> searcher = new BinarySearcher<Task>(tasks,
(x, y) => Comparer<DateTime>.Default.Compare(x.StartTime, y.StartTime));
foreach (Task t in searcher.Between(
new Task() { StartTime = new DateTime(2009, 02, 13) },
new Task() { StartTime = new DateTime(2009, 02, 10) }))
{
// Write.
Console.WriteLine(t);
}