我想写一个排序逻辑来排序下面的字符串作为一个自定义类的输出:
现在输出:3m_20,2m_20,1m_20,10d_20,5d_20,0d_20,0d_0,5d_0,10d_0,1m_0,2m_0,3m_0
所需输出:0d_0,0d_20,5d_0,5d_20,10d_0,10d_20,1m_0,1m_20,2m_0,2m_20,3m_0,3m_20
我发现很难按上述方式进行复杂的排序。请帮助我如何按要求排序?
我试过在Id
的基础上用IComparable
对它排序,但它的排序是在第一个字符的基础上。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace Rextester
{
public class Program
{
public static void Main(string[] args)
{
DateDefinition d1 = new DateDefinition { Horizon = "0d",Days=20};
DateDefinition d1_0 = new DateDefinition { Horizon = "0d",Days=0};
DateDefinition d2 = new DateDefinition { Horizon = "5d",Days=20};
DateDefinition d2_0 = new DateDefinition { Horizon = "5d",Days=0};
DateDefinition d3 = new DateDefinition { Horizon = "10d",Days=20};
DateDefinition d3_0 = new DateDefinition { Horizon = "10d",Days=0};
DateDefinition d4 = new DateDefinition { Horizon = "1m",Days=20};
DateDefinition d4_0 = new DateDefinition { Horizon = "1m",Days=0};
DateDefinition d5 = new DateDefinition { Horizon = "2m",Days=20};
DateDefinition d5_0 = new DateDefinition { Horizon = "2m",Days=0};
DateDefinition d6 = new DateDefinition { Horizon = "3m",Days=20};
DateDefinition d6_0 = new DateDefinition { Horizon = "3m",Days=0};
var definitions = new List<DateDefinition> {d6,d5,d4,d3,d2,d1,d1_0,d2_0,d3_0,d4_0,d5_0,d6_0};
definitions.Sort();
foreach(var d in definitions)
{
Console.WriteLine(d.Id);
}
}
}
public class DateDefinition : IComparable<DateDefinition>
{
public string Horizon { get; set; }
public int Days { get; set; }
public string Id
{
get { return Horizon + "_" + Days.ToString(); }
}
public int CompareTo(DateDefinition other)
{
if (ReferenceEquals(other, this)) return 0;
if(ReferenceEquals(other,null)) return -1;
return string.Compare(Id,other.Id, StringComparison.InvariantCultureIgnoreCase);
}
}
}
输出到上面的代码:0d_0 0d_20 10d_0 10d_20 1m_0 1m_20 2m_0 2m_20 3m_0 3m_20 5d_0 5d_20
需要输出如下:0d_0 0d_20 5d_0 5d_20 10d_0 10d_20 1m_0 1m_20 2m_0 2m_20 3m_0 3m_20
重要提示:请注意,在上述上下文中,d=天,m=月。
3条答案
按热度按时间gdrx4gfi1#
在
CompareTo
方法中,您使用的是string.Compare
,因此它按字母顺序比较两个示例的计算Id属性。按字母顺序,“10d_0”在“5d_0”之前。您希望进行某种数值比较,但需要将以月为单位的展望期值转换为以天为单位的展望期值(反之亦然),才能进行有效的比较。
将Horizon属性定义为字符串似乎有点困难,因为它似乎包含一个数字和单位(d表示天数,m表示月份)。您需要解析这些内容并将其转换为数字,或者将Horizon重新定义为数值HorizonValue和字符串HorizonUnits。
1dkrff032#
您需要CompareTo()来实现您的自定义业务规则。据我所知,您的算法将是:
wh6knrhe3#
类别
DateDefinition
必须实作IComparable<DateDefinition>
,排序才能如预期般运作。在下面的示例中,我向
Horizon
属性添加了一些逻辑。setter将传递的字符串拆分为一个数字和一个单位,并将它们存储在char? _horizonUnit; int? _horizonNumber;
字段中;getter组合这些部分以重新创建原始字符串。
如果
this
小于other
,则ComparesTo
返回-1;如果两者相等,则ComparesTo
返回0;如果this
大于other
,则ComparesTo
返回+1。首先,它比较单位。碰巧
'd'
小于'm'
,因此,内置的Char.CompareTo
返回所需的订单。如果单位相等,我们比较展望期编号。如果它们也相等,我们比较Days
。请注意,我已经重写了
ToString
,让它返回Id
。因此,现在您可以简单地编写Console.WriteLine(d);
。这对于调试也更好,因为调试器现在显示DateDefinition
对象的Id
。还要注意,我使用了C#的新Indexes and Ranges特性。如果您不能使用它们,可以使用
String.Subtring
代替(这有点麻烦)。