CompareTo 未产生预期的排序顺序
CompareTo Not Resulting in Expected Sort Order
正在尝试对以下列表进行排序:
public class BusinessEvents : IComparable<BusinessEvent>
{
public long VersionId {get;set;}
public EventType EventType {get;set;}
}
排序逻辑如下:
public int CompareTo(BusinessEvent businessEvent)
{
if (VersionId > businessEvent.VersionId)
{
return 1;
}
if (VersionId < businessEvent.VersionId)
{
return -1;
}
if (EventType == EventType.TypeC ||
EventType == EventType.TypeD ||
EventType == EventType.TypeE)
{
if (businessEvent.EventType == EventType.TypeA ||
businessEvent.EventType == EventType.TypeB)
{
return 1;
}
}
return 0;
}
但是,这个单元测试失败了:
[Test]
public void BusinessEvent_Sort_Correctly_Break_Ties_Multiple()
{
// arrange
var event1 = GetEventWithTypeAndVersionId(1, EventType.TypeA);
var event2 = GetEventWithTypeAndVersionId(1, EventType.TypeD);
var event3 = GetEventWithTypeAndVersionId(1, EventType.TypeC);
var event4 = GetEventWithTypeAndVersionId(2, EventType.TypeB);
var event5 = GetEventWithTypeAndVersionId(2, EventType.TypeE);
var event6 = GetEventWithTypeAndVersionId(2, EventType.TypeC);
var events = new List<BusinessEvent> {event4, event2, event5, event6, event3, event1};
// act
events = events.OrderBy(c => c).ToList();
// assert
Assert.AreEqual(EventType.TypeA, events[0].EventType);
Assert.AreEqual(EventType.TypeD, events[1].EventType);
Assert.AreEqual(EventType.TypeC, events[2].EventType);
Assert.AreEqual(EventType.TypeB, events[3].EventType);
Assert.AreEqual(EventType.TypeE, events[4].EventType);
Assert.AreEqual(EventType.TypeC, events[5].EventType);
}
第一次断言就失败了。它将 EventType.TypeD
和 VersionId
放在排序列表的第一位,即使我指定 EventType.TypeD
在 EventType.TypeA
之后当 VersionId
匹配时也是如此。
很明显,我误解了 API 提供的内容。我怎样才能得到我预期的结果?
问题是当 this.EventType
是 TypeA
或 TypeB
时,您还没有 returning -1
,你 return 0
那样的话。
您还可以通过使用 int.CompareTo
来处理各种情况来简化此操作。实现自定义比较逻辑的最佳方法是在每个级别上使用标准 CompareTo
并检查 != 0
.
public int CompareTo(BusinessEvent businessEvent)
{
var cmp = VersionId.CompareTo(businessEvent.VersionId);
if (cmp != 0)
return cmp;
cmp = (EventType == EventType.TypeA || EventType == EventType.TypeB ? 0 : 1)
.CompareTo(
businessEvent.EventType == EventType.TypeA ||
businessEvent.EventType == EventType.TypeB ? 0 : 1);
return cmp;
}
其工作方式是将 TypeA
和 TypeB
转换为 0
,将其他所有内容转换为 1
,然后进行比较。显然 0
在 1
.
之前排序
您可以通过编写某种将不同 EventType
合并在一起的转换函数来添加更多条件或排序。
正在尝试对以下列表进行排序:
public class BusinessEvents : IComparable<BusinessEvent>
{
public long VersionId {get;set;}
public EventType EventType {get;set;}
}
排序逻辑如下:
public int CompareTo(BusinessEvent businessEvent)
{
if (VersionId > businessEvent.VersionId)
{
return 1;
}
if (VersionId < businessEvent.VersionId)
{
return -1;
}
if (EventType == EventType.TypeC ||
EventType == EventType.TypeD ||
EventType == EventType.TypeE)
{
if (businessEvent.EventType == EventType.TypeA ||
businessEvent.EventType == EventType.TypeB)
{
return 1;
}
}
return 0;
}
但是,这个单元测试失败了:
[Test]
public void BusinessEvent_Sort_Correctly_Break_Ties_Multiple()
{
// arrange
var event1 = GetEventWithTypeAndVersionId(1, EventType.TypeA);
var event2 = GetEventWithTypeAndVersionId(1, EventType.TypeD);
var event3 = GetEventWithTypeAndVersionId(1, EventType.TypeC);
var event4 = GetEventWithTypeAndVersionId(2, EventType.TypeB);
var event5 = GetEventWithTypeAndVersionId(2, EventType.TypeE);
var event6 = GetEventWithTypeAndVersionId(2, EventType.TypeC);
var events = new List<BusinessEvent> {event4, event2, event5, event6, event3, event1};
// act
events = events.OrderBy(c => c).ToList();
// assert
Assert.AreEqual(EventType.TypeA, events[0].EventType);
Assert.AreEqual(EventType.TypeD, events[1].EventType);
Assert.AreEqual(EventType.TypeC, events[2].EventType);
Assert.AreEqual(EventType.TypeB, events[3].EventType);
Assert.AreEqual(EventType.TypeE, events[4].EventType);
Assert.AreEqual(EventType.TypeC, events[5].EventType);
}
第一次断言就失败了。它将 EventType.TypeD
和 VersionId
放在排序列表的第一位,即使我指定 EventType.TypeD
在 EventType.TypeA
之后当 VersionId
匹配时也是如此。
很明显,我误解了 API 提供的内容。我怎样才能得到我预期的结果?
问题是当 this.EventType
是 TypeA
或 TypeB
时,您还没有 returning -1
,你 return 0
那样的话。
您还可以通过使用 int.CompareTo
来处理各种情况来简化此操作。实现自定义比较逻辑的最佳方法是在每个级别上使用标准 CompareTo
并检查 != 0
.
public int CompareTo(BusinessEvent businessEvent)
{
var cmp = VersionId.CompareTo(businessEvent.VersionId);
if (cmp != 0)
return cmp;
cmp = (EventType == EventType.TypeA || EventType == EventType.TypeB ? 0 : 1)
.CompareTo(
businessEvent.EventType == EventType.TypeA ||
businessEvent.EventType == EventType.TypeB ? 0 : 1);
return cmp;
}
其工作方式是将 TypeA
和 TypeB
转换为 0
,将其他所有内容转换为 1
,然后进行比较。显然 0
在 1
.
您可以通过编写某种将不同 EventType
合并在一起的转换函数来添加更多条件或排序。