【问题标题】:CompareTo Not Resulting in Expected Sort OrderCompareTo 未产生预期的排序顺序
【发布时间】:2021-07-29 21:57:16
【问题描述】:

尝试对这些列表进行排序:

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.TypeDVersionId 放在排序列表的第一位,即使当VersionId 匹配时我指定EventType.TypeDEventType.TypeA 之后。

显然我误解了这个 API 提供的一些东西。我怎样才能得到我的预期结果?

【问题讨论】:

  • events.OrderBy(c =&gt; c).ToList() 不改变订单?
  • 不确定你的意思。顺序正在改变,根据我对 API 的理解,它似乎不是正确的顺序。

标签: c# .net compareto


【解决方案1】:

问题是,当this.EventTypeTypeATypeB 时,您不会同时返回-1,在这种情况下您返回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;
}

其工作方式是将TypeATypeB 转换为0,并将其他所有内容转换为1,然后进行比较。显然0 排在1 之前。

您可以通过编写某种将不同EventType 合并在一起的转换函数来添加更多条件或排序。

【讨论】:

  • 谢谢,这行得通,但我不太清楚为什么。我想我需要研究一下使 CompareTo 调用的逻辑如何处理 -1/0/1 的响应
  • 已添加说明。不是CompareTo 本身在做,而是三元组? 0 : 1
猜你喜欢
  • 2020-01-05
  • 2011-07-26
  • 2011-02-25
  • 2015-11-06
  • 2012-08-11
  • 2017-08-15
  • 2021-10-13
  • 2017-07-16
  • 1970-01-01
相关资源
最近更新 更多