按自定义顺序按枚举顺序排列对象

时间:2017-12-04 10:10:54

标签: c#

我试图按照中,大,小的顺序重新排列动物列表。我一直试图用IComparable.CompareTo来做这件事,但我无法弄清楚如何以这种特定的方式订购它。我只能通过升序或降序来找到订购方式。

我的枚举:

public enum AnimalSize
    {
        Small = 1, Medium = 3, Large = 5,
    }

我的动物类:

public class Animal : IComparable<Animal>
{
    public bool IsCarnivore;
    public AnimalSize Size;

    public Animal(bool isCarnivore, AnimalSize size)
    {
        this.IsCarnivore = isCarnivore;
        this.Size = size;
    }

    public int CompareTo(Animal other)
    {
        return this.Size.CompareTo(other.Size);
    }

我从另一个班级调用CompareTo,我有一个私人动物列表。

如何按中,大,小的顺序排列动物?

4 个答案:

答案 0 :(得分:4)

我不会为动物等非标量对象实现IComparable<T>。如果你想按高度而不是大小排序怎么办?或者通过名字? IComparable意味着可以将对象转换为一维数量。

相反,在数组中定义所需的排序顺序,并使用简单的LINQ查询进行排序。

public static void Main()
{
    var sampleData = new List<Animal>
    {
        new Animal(false, AnimalSize.Small),
        new Animal(false, AnimalSize.Large),
        new Animal(false, AnimalSize.Medium)
    };

    AnimalSize[] customSortOrder = new[]
    {
        AnimalSize.Small,
        AnimalSize.Medium,
        AnimalSize.Large
    };

    var results = sampleData.OrderBy( a => Array.IndexOf(customSortOrder, a.Size ));

    foreach (var a in results)
    {
        Console.WriteLine(a.Size);
    }

输出:

Small
Medium
Large

Code on DotNetFiddle

答案 1 :(得分:1)

您可以创建自定义Comparer<Animal>

public class AnimalSizeComparer : Comparer<Animal>
{
    private readonly IList<AnimalSize> _order;

    public AnimalSizeComparer():this(Enum.GetValues(typeof(AnimalSize)).Cast<AnimalSize>().ToArray())
    {
    }
    public AnimalSizeComparer(IList<AnimalSize> order)
    {
        _order = order;
    }

    public override int Compare(Animal x, Animal y)
    {
        if (x == null && y == null) return 0;
        if (x == null) return -1;
        if (y == null) return 1;

        return _order.IndexOf(x.Size).CompareTo(_order.IndexOf(y.Size));
    }
}

您可以通过以下方式使用示例订单对其进行初始化:

var comparer = new AnimalSizeComparer(new[] { AnimalSize.Medium, AnimalSize.Large, AnimalSize.Small });
yourAminalList.Sort(comparer);

答案 2 :(得分:0)

如果你想使用IComparable,你需要先转换为int。

public int CompareTo(Animal other)
        {
            return ((int)this.Size).CompareTo((int)other.Size);
        }

通过此更改,调用包含动物对象的列表的Sort()函数将按预期工作。

答案 3 :(得分:0)

在比较(未测试)之前,您可以检查它们中的任何一个是否为中等:

public int CompareTo(Animal other)
{
    if (this.Size == other.Size) return 0;
    if (this.Size == AnimalSize.Medium) return -1;
    if (other.Size == AnimalSize.Medium) return 1;

    return this.Size.CompareTo(other.Size);
}

在没有分支错误预测的情况下效率更高(3变为1,5⇒3和1⇒7):

public int CompareTo(Animal other) => ((int)this.Size + 2 ^ 4) - ((int)other.Size + 2 ^ 4);

或查找数组(3⇒1,5⇒2和1⇒3):

byte[] order = { 0, 3, 0, 1, 0, 2 };

public int CompareTo(Animal other) => order[(byte)this.Size] - order[(byte)other.Size];