【问题标题】:How to sort strings by a different value如何按不同的值对字符串进行排序
【发布时间】:2013-03-05 13:08:44
【问题描述】:

我已经尝试寻找一个现有的问题,但不知道如何表达这个问题,这在任何地方都没有检索到任何结果:(

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

因为我对这类事情有强迫症,所以我希望元素不是按字母数字值的大小排序,而是按自定义顺序的大小排序。

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

分解一下,如果我有一个这些订单商品的列表,每个商品都有一个尺寸,如下所示:

2XL
S
5XL
M

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

2XL
5XL
M
S

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

S
M
2XL
5XL

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

我希望订单是动态的原因是订单项目在运行时从硬盘上的文件加载,并且用户在运行时添加/编辑/删除,它们可能包含的大小我没有硬编码,例如我可以从 10XS 一直硬编码到 10XL,但是如果有人添加尺寸“110cm”(又名 Medium),它会以我不想要的顺序出现假设程序没有崩溃和烧毁。

我不知道该怎么做。

【问题讨论】:

  • 项目加载时加载到哪里?进入数据库?你不能在这里应用订单索引吗?
  • 我刚刚回答了一个类似的问题,这是我的回答:stackoverflow.com/questions/15223213/…
  • 如果有人加了110cm,你怎么知道它的意思?
  • 蒂姆:问题就在这里。我担心我可能只需要删除自定义尺寸输入并给用户一个列表,然后对订单进行硬编码。 Liam:这些项目只是加载到一个 Order 类中,该类是一个继承自 List 的自定义类,我在其中添加了一些方法来检索与某些字段匹配的项目。 Nolonar:谢谢,我现在去看看。

标签: c# sorting


【解决方案1】:

另外,您可以创建一个Dictionary<int, string> 并在下面添加Key as 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();

【讨论】:

  • @CliftonJKent 我仍然会将其包装在 IComparer&lt;string&gt; 中,以便其可重复使用。
  • @DanielA.White 是的,这也是有道理的。也许我可以尝试将每个大小解析为一个整数值,并将其用作键。
【解决方案2】:

你可以直接使用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。

【讨论】:

  • 这会有很多开销。
  • 这不是“硬编码”命令吗? OP 试图避免哪个?
  • 我认为这就是硬编码的意思。 @DanielA.White:开销是多少?这类似于 if-else 或 sql 中的 ORDER BY a DESC, B DESC, C DESC, ...
  • 它循环了几次。更不用说字符串相等的内部循环了。
  • @DanielA.White:我认为你误解了OrderBy...ThenBy 的工作原理。他们不需要一直对所有元素重新排序。仅当OrderBy 返回两个相等的元素时才查询ThenBystackoverflow.com/a/10827971/284240
【解决方案3】:

我会将IComparer&lt;string&gt; 实现为您自己的TShirtSizeComparer。您可能需要执行一些正则表达式才能获得所需的值。

IComparer&lt;T&gt; 是任何排序机制的绝佳接口。 .NET 框架中的许多内置内容都使用它。它使排序可重用

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

【讨论】:

    【解决方案4】:

    你需要在你的类上实现IComparer 接口。你可以谷歌如何做到这一点,因为那里有很多例子

    【讨论】:

    • 我看过 IComparer,不过这不是硬编码的解决方案吗?
    • @CliftonJKent 使用Icomparer 进行了一些硬编码,但您可以将逻辑放入决策表中。
    【解决方案5】:

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

    【讨论】:

      【解决方案6】:

      我会用 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;
          }
      }
      

      【讨论】:

        【解决方案7】:

        我用基类Comparer&lt;object&gt; 实现了TShirtSizeComparer。当然,您必须将其调整为可用的大小和对象:

        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());
        

        “硬编码”的顺序优先,其余的放在后面。

        我确信它可以做得更智能、更通用,以避免对所有内容进行硬编码。你可以例如查找以“S”结尾的尺寸,然后检查有多少个 X(例如 XXS)或 X 之前的数字(例如 2XS)并按此排序,然后重复“L”以及其他“主要尺寸”。

        【讨论】:

          猜你喜欢
          • 2015-11-27
          • 2014-10-28
          • 1970-01-01
          • 2012-03-16
          • 2013-09-04
          • 1970-01-01
          • 2011-10-09
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多