2016-12-15 66 views
2

我正在寻找一种方法来实现基于DateTime值确保订单的集合。我最初的想法是使用SortedSet<T1>使用自定义IComparer<T1>这样的:基于DateTime的已订购集合

internal class DateTimeComparer : IComparer<MyType> { 
    public int Compare(MyType x, MyType y) { 
     return x.DateTimeProp.CompareTo(y.DateTimeProp); 
    } 
} 

var sortedSet = new SortedSet<MyType>(new DateTimeComparer()); 

但是作为设定似乎覆盖/替换其中有确切的时间戳的所有项目,这并不工作。为了验证这个假设,我创建了两个集合,一个是简单列表,它在填充后使用DateTime属性进行排序,另一个是基于SortedSet<T1>的另一个属性 - >基于该集合的列表中有几个条目丢失,那些具有完全相同的时间戳的那些。

还有什么其他的选择来实现这样一个集合?

+1

任何你不想把所有东西都添加到列表中然后对其进行排序的原因? –

+0

你尝试过'SortedList'吗? (请注意,排序列表比正常列表慢,因为每次访问具有索引的项目时,它都执行二进制搜索,而列表将直接为您提供该索引内的项目) –

+0

一个集合只能包含特定值一次。使用'DateTimeComparer'时,如果两个值具有相同的时间戳,则认为它们是相同的,因此即使在考虑其他属性时值不同,您也只能为特定时间戳存储单个值。 –

回答

1

维护项目排序集合的有效方法是使用二叉搜索树。您当然可以构建自己的二叉搜索树,但SortedSet<T>类是使用红黑二叉搜索树实现的,因此重用该类正是您正在尝试执行的操作似乎更智能。

SortedSet<T>中物品的排序通过调用IComparer<T>.Compare方法比较物品对来控制。如果此方法返回0,则两个项目被视为相等,并且只有其中一个项目将存储在该集合中。在DateTimeComparer的情况下,您会遇到这样的问题,只有一个具有指定DateTimePropMyType实例可以存储在该集合中。

要解决此问题,必须确保使用DateTimeComparer.Compare方法进行比较时,不同的MyType实例永远不会相等。您可以通过修改代码来实现这一目标:

class DateTimeComparer : IComparer<MyType> { 

    readonly ObjectIDGenerator idGenerator = new ObjectIDGenerator(); 

    public int Compare(MyType x, MyType y) { 
     if (x.DateTimeProp != y.DateTimeProp) 
      return x.DateTimeProp.CompareTo(y.DateTimeProp); 
     bool firstTime; 
     var xId = idGenerator.GetId(x, out firstTime); 
     var yId = idGenerator.GetId(y, out firstTime); 
     return xId.CompareTo(yId); 
    } 
} 

如果两个实例有DateTimeProp那么他们应该根据这些订购不同的值。这是由最初的if声明处理的。

如果这两个值具有相同的DateTimeProp值,则需要根据其他一些条件对其进行排序。您可以使用MyType的其他属性,但可能会出现这些属性相同的情况,除非xy引用相同的实例(例如ReferenceEquals(x, y)为true),否则该方法从不返回0是很重要的。

要处理这个问题,您可以使用ObjectIDGenerator,它将为不同的实例分配唯一的64位ID值。这些可以进行比较以提供订购。

请注意,具有相同DateTimeProp值的项目排序将是随机的但一致。要控制这种排序,您可以使用MyType的其他属性,但最终,如果两个不同实例的所有属性都相同,则必须使用生成的ID来提供排序。

+0

当两个时间戳相等时,我通过简单地返回'大于'(1)来解决这个问题。 – artganify