如何按不同的值对字符串进行排序

时间:2013-03-05 13:08:44

标签: c# sorting

我已经尝试过寻找现有问题,但我不确定如何对此进行说明,而且这在任何地方都没有检索到结果:(

无论如何,我有一类"订购商品"具有不同的属性。这些订单商品用于服装,因此它们的尺寸(字符串)。

因为我是关于这些事情的OCD,所以我希望元素不是按字母数字值排序,而是按自定义顺序排序。

如果可能的话,我也希望不会对此自定义订单进行硬编码。

要将其细分,如果我有这些订单商品的清单,每个订单商品的尺寸如下:

2XL
S
5XL
M

使用字母数字排序,它将按以下顺序排列:

2XL
5XL
M
S

但我想将此列表排序为此顺序( 从最小尺寸到最大 ):

S
M
2XL
5XL

我能想到的唯一方法是使用硬编码的大小数组并按索引排序,然后当我需要获取大小值时,我可以获取大小顺序数组[i]值。但是,正如我所说,我希望这个命令不要硬编码。

我希望订单是动态的原因是订单项在运行时从硬盘上的文件加载,并且还在运行时由用户添加/编辑/删除,并且它们可能包含我没有硬编码,例如我可以从10XS到10XL一直硬编码但是如果有人增加尺寸" 110cm" (也称为中等),假设程序没有崩溃和烧毁,它将按照我不想要的顺序出现在某个地方。

我无法完全理解如何做到这一点。

7 个答案:

答案 0 :(得分:5)

您可以直接使用OrderByDescending + ThenByDescending

sizes.OrderByDescending(s => s == "S")
     .ThenByDescending( s => s == "M")
     .ThenByDescending( s => s == "2XL")
     .ThenByDescending( s => s == "5XL")
     .ThenBy(s => s);

我使用...Descending,因为true类似于1而false为0。

答案 1 :(得分:5)

此外,您可以在下方创建Dictionary<int, string>并添加Key Ordering order。在Keys之间留出一些空白,以适应未来的新尺寸。例如:如果您要添加L (Large),则可以在不中断当前订单的情况下将新项目添加为{15, "L"}

 Dictionary<int, string> mySizes = new Dictionary<int, string> { 
                                       { 20, "2XL" }, { 1, "S" },
                                       { 30, "5XL" }, { 10, "M" }
                                    };

 var sizes = mySizes.OrderBy(s => s.Key)
                    .Select(s => new {Size =  s.Value})
                    .ToList();

答案 2 :(得分:3)

我会将IComparer<string>实施到您自己的TShirtSizeComparer中。您可能需要执行一些正则表达式来获取所需的值。

IComparer<T>是任何排序机制的绝佳界面。 .NET框架中的许多内置东西都使用它。它使排序可重复使用

我真的建议将大小字符串解析为一个单独的对象,该对象具有大小编号和大小,然后用它进行排序。

答案 3 :(得分:1)

您需要在班级上实施IComparer界面。您可以谷歌如何做到这一点,因为那里有很多例子

答案 4 :(得分:0)

你必须为此做一个简单的解析器。您可以在字符串中搜索XS XL和cm等元素,“如果你过滤掉你的单位。那么你可以获得整数值。如果你有,你确实可以使用IComparer对象,但它没有没有那么大的优势。

答案 5 :(得分:0)

我会用Size创建一个类,很可能你将来需要添加更多功能。我添加了大小的全名,但您也可以添加宽度和长度等变量,以及英寸或厘米的转换器。

private void LoadSizes()
{
    List<Size> sizes = new List<Size>();
    sizes.Add(new Size("2X-Large", "2XL", 3));
    sizes.Add(new Size("Small", "S", 1));
    sizes.Add(new Size("5X-Large", "5XL", 4));
    sizes.Add(new Size("Medium", "M", 2));

    List<string> sizesShortNameOrder = sizes.OrderBy(s => s.Order).Select(s => s.ShortName).ToList();
    //If you want to use the size class:
    //List<Size> sizesOrder = sizes.OrderBy(s => s.Order).ToList();
}

public class Size
{
    private string _name;
    private string _shortName;
    private int _order;

    public string Name
    {
        get { return _name; }
    }

    public string ShortName
    {
        get { return _shortName; }
    }

    public int Order
    {
        get { return _order; }
    }

    public Size(string name, string shortName, int order)
    {
        _name = name;
        _shortName = shortName;
        _order = order;
    }
}

答案 6 :(得分:0)

我使用基类TShirtSizeComparer实现了Comparer<object>。当然,您必须根据可用的尺寸和对象进行调整:

public class TShirtSizeComparer : Comparer<object>
{
    // Compares TShirtSizes and orders them by size
    public override int Compare(object x, object y)
    {
        var _sizesInOrder = new List<string> { "None", "XS", "S", "M", "L", "XL", "XXL", "XXXL", "110 cl", "120 cl", "130 cl", "140 cl", "150 cl" };
        var indexX = -9999;
        var indexY = -9999;
        if (x is TShirt)
        {
            indexX = _sizesInOrder.IndexOf(((TShirt)x).Size);
            indexY = _sizesInOrder.IndexOf(((TShirt)y).Size);
        }
        else if (x is TShirtListViewModel)
        {
            indexX = _sizesInOrder.IndexOf(((TShirtListViewModel)x).Size);
            indexY = _sizesInOrder.IndexOf(((TShirtListViewModel)y).Size);
        }
        else if (x is MySelectItem)
        {
            indexX = _sizesInOrder.IndexOf(((MySelectItem)x).Value);
            indexY = _sizesInOrder.IndexOf(((MySelectItem)y).Value);
        }
        if (indexX > -1 && indexY > -1)
        {
            return indexX.CompareTo(indexY);
        }
        else if (indexX > -1)
        {
            return -1;
        }
        else if (indexY > -1)
        {
            return 1;
        }
        else
        {
            return 0;
        }
    }
}

要使用它,你只需要一个List或你的对象是什么和做什么:

tshirtList.Sort(new TShirtSizeComparer());

您拥有的订单&#34;硬编码&#34;优先考虑,其余部分放在后面。

我确信它可以做得更聪明,更通用,以避免硬编码。你可以,例如寻找以&#34; S&#34;然后检查多少X(例如XXS)或X之前的数字(例如2XS)并按此排序,然后重复&#34; L&#34;或者其他&#34;主要尺寸&#34;。