【问题标题】:Sorting List<TextBox> Numerically C#数字排序列表<TextBox> C#
【发布时间】:2016-06-27 13:24:34
【问题描述】:

我将这些TextBoxes 标记为tb_class## = 1-10

到目前为止,这是我拥有的功能

    private List<TextBox> GetCustomClasses()
    {
        List<TextBox> tb = new List<TextBox>();
        foreach (Control con in gb_customClasses.Controls)
            if (con.Name.Contains("tb_class"))
                tb.Add(con as TextBox);
        return tb.OrderByDescending(x => x.Name.Replace("tb_class", "")).ToList();
    }

输出如下:

9
8
7
6
5
4
3
2
10
1

我可以为此添加一张支票,但我希望它以完美的顺序运行。对于那些想知道gb_customClassesgroupbox 的人。

解决了!最终代码:

    private List<TextBox> GetCustomClasses()
    {
        List<TextBox> tb = new List<TextBox>();
        foreach (Control con in gb_customClasses.Controls)
            if (con.Name.Contains("tb_class"))
                tb.Add(con as TextBox);
        return tb.OrderByDescending(x => int.Parse(x.Name.Replace("tb_class", ""))).ToList();
    }

我什至没有考虑添加int.Parse

【问题讨论】:

  • 替换前请出示数据。显然,您已经按字符串排序,而不是数字类型。
  • 这很简单 - 您正在处理控件的名称,它们是字符串。如果您按字母顺序排序,它们是按顺序排列的!您需要将它们作为数字类型进行比较,以使其按您想要的顺序运行。
  • 您可以对这种事情使用自然排序顺序 - have a look at my answer herethis answer here

标签: c# linq list sorting


【解决方案1】:

您必须将其转换为 int,这是一种仅限 LINQ 的方法:

private List<TextBox> GetCustomClasses()
{
    return gb_customClasses.Controls.OfType<TextBox>()
        .Where(txt => txt.Name.StartsWith("tb_class"))
        .OrderByDescending(txt => int.Parse(txt.Name.Substring("tb_class".Length)))
        .ToList();
}

【讨论】:

    【解决方案2】:

    您必须进行数字排序,而不是按字典顺序排序。试试这个:

    return tb.OrderByDescending(x => int.Parse(x.Name.Replace("tb_class", ""))).ToList();
    

    请注意,您可能不必致电.ToList(),具体取决于您的情况。返回 IEnumerable&lt;TextBox&gt; 可能会有用 - 所以请检查一下。


    不要害怕使用Tag 属性在控件上存储一些额外信息!这个解决方案更好一些:

    return tb.OrderByDescending(x => (int)x.Tag);
    

    return tb.OrderByDescending(x => ((MyClass)x.Tag).Index);
    

    您只需确保为添加到gb_customClasses.Controls 的任何TextBox 添加适当的Tag。如果控件是动态创建的,我会倾向于这种方法(然后标记很容易,命名甚至不是必须的)

    【讨论】:

      【解决方案3】:

      您正在按字母顺序对它们进行排序,请将您的 return 语句更改为:

      return tb.OrderByDescending(x => Int32.Parse(x.Name.Replace("tb_class", ""))).ToList();
      

      为了让列表按数字排序

      【讨论】:

        【解决方案4】:

        您应该将它们作为数字而不是字符串进行比较:

        return tb.OrderByDescending(x => Convert.ToInt32(x.Name.Replace("tb_class", ""))).ToList();
        

        添加这一点会将您删除 tb_class 的名称从字符串转换为 int。

        【讨论】:

          【解决方案5】:

          修改为

          OrderByDescending(x => Convert.ToInt32(x.Name.Replace("tb_class", "")))

          【讨论】:

            【解决方案6】:

            我将这些文本框标记为“tb_class#”并且# = 1-10

            通过这种编码,您可以利用数字越大的事实,并且LINQ排序稳定。换句话说,只需先按文本长度排序,然后按文本排序:

            return tb.OrderByDescending(x => x.Name.Length).ThenByDescending(x => x.Name).ToList();
            

            【讨论】:

              【解决方案7】:

              这可能有效:

              private List<TextBox> GetCustomClasses()
              {
                  List<TextBox> tb = new List<TextBox>();
              
                  List<String> indexes = new List<string>();
              
                  //  N.B. A more conservative implementation might want to go for an unsigned 
                  //  64-bit thing here. Just in case you run into a really big GroupBox.
                  //  
                  //  **WARNING** Due to Brexit, UK compilers will be changing to base 12, which 
                  //  may adversely affect the performance of this loop. Also keep an eye out for 
                  //  unpredictable fluctuations in the exchange rate with UK integers. 
              
                  for (String i = "0"; Int32.Parse(i) < 0x7fffffff; i = (Int32.Parse(i) + 1).ToString())
                  {
                      indexes = indexes.Union(new string[] { i }).ToList();
                  }
              
                  var arrayOfIndexes = indexes.ToArray();
              
                  //  Leave room for null terminator
                  var reordered = new TextBox[gb_customClasses.Controls.Count + 1];
              
                  foreach (Control con in gb_customClasses.Controls)
                      if (con.Name.Contains("tb_class"))
                          reordered[arrayOfIndexes.ToList().IndexOf(con.Name.Replace("tb_class", ""))] = con as TextBox;
              
                  return reordered.ToList();
              }
              

              【讨论】:

              • 众所周知不需要的肤色
              • @SimpleVar 我应该让indexes 无符号吗?
              • 不确定是否巨魔..?至少你应该知道List&lt;T&gt; 有一个Add 方法,而不是.Union().ToList()
              • 那么为什么要遍历字符串直到0x7fffffff?我的意思是,我想它可以作为一个巨魔帖子传递
              • “还要留意英国整数汇率的不可预测波动。” -- 发生了什么
              猜你喜欢
              • 1970-01-01
              • 2011-07-24
              • 2019-11-14
              • 2014-07-15
              • 1970-01-01
              • 2013-07-30
              • 1970-01-01
              • 1970-01-01
              • 2018-01-14
              相关资源
              最近更新 更多