按数字排序字符串列表

时间:2016-10-26 05:05:05

标签: c# linq list sorting

我有一个以下字符串列表:

List<string> a = new List<string>();

a.Add("2015");
a.Add("2015 /M1");
a.Add("2015 /M2");
a.Add("2015 /M9");
a.Add("2015 /M10");
a.Add("2015 /M11");
a.Add("2015 /M12");
a.Add("2015 /M3");
a.Add("2015 /M4");
a.Add("2015 /M5");
a.Add("2015 /M6");
a.Add("2015 /M7");
a.Add("2015 /M8");

当我调用sort函数a.sort()时,它会像这样排序:

2015
2015 /M1
2015 /M11
2015 /M12
2015 /M2
2015 /M3
2015 /M4
2015 /M5
2015 /M6
2015 /M7
2015 /M8
2015 /M9

但我如何修改使其看起来如下。

2015
2015 /M1
2015 /M2
2015 /M3
2015 /M4
2015 /M5
2015 /M6
2015 /M7
2015 /M8
2015 /M9
2015 /M10
2015 /M11
2015 /M12

我在其他列表项目中也有相同的模式,例如2015 Q / 12,2015 Q / 11等。

6 个答案:

答案 0 :(得分:3)

你需要从字符串中提取数字,它可以通过正则表达式来完成。然后将其转换为整数并按其排序。

var e = from s in a
        let g = Regex.Match(s, @"^\d+(?: \/[MQ](\d+))?$")
        let n = g.Groups[1].Value != "" ? int.Parse(g.Groups[1].Value) : (int?)null
        orderby n
        select s;

a = e.ToList();

修改

要按年份排序,请使用以下代码

var e = from s in a
        let g = Regex.Match(s, @"^[A-Za-z]*(\d+)(?: \/[MQ](\d+))?$")
        let y = g.Groups[1].Value != "" ? int.Parse(g.Groups[1].Value) : 0
        let m = g.Groups[2].Value != "" ? int.Parse(g.Groups[2].Value) : 0                    
        orderby y, m      
        select s;

答案 1 :(得分:1)

我这样做了:

var results =
    a
        .OrderBy(x => new string(x.Take(7).ToArray()))
        .ThenBy(x => int.Parse(new string(x.Skip(7).DefaultIfEmpty('0').ToArray())));

......得到了这个:

2015 
2015 /M1 
2015 /M2 
2015 /M3 
2015 /M4 
2015 /M5 
2015 /M6 
2015 /M7 
2015 /M8 
2015 /M9 
2015 /M10 
2015 /M11 
2015 /M12 

答案 2 :(得分:1)

您正在寻找natural sort order。 在链接的问题中,您可以找到一个纯LINQ实现,可以重用于任何自然排序顺序问题。

答案 3 :(得分:0)

This帖子与您的相似。根据您的要求编辑:

var sortedList = a.OrderBy(x => PadNumbers(!x.Contains("M")? "" : x.Substring(x.IndexOf('M'), (x.Length - x.IndexOf('M'))))).ToList();

public static string PadNumbers(string input)
{
    return Regex.Replace(input, "[0-9]+", match => match.Value.PadLeft(10, '0'));
}

答案 4 :(得分:0)

我已经详细阐述了Niyoko Yuliawans解决方案,结果是:

  class StringComparer : IComparer<string>
  {
    const string pattern = @"^\D*(?<year>\d{4})( \/[MQ](?<index>\d+))?$";

    public int Compare(string x, string y)
    {
      var mx = Regex.Match(x, pattern);
      var my = Regex.Match(y, pattern);

      int ix;
      if (int.TryParse(mx.Groups["index"].Value, out ix))
      {
        int iy;
        if (int.TryParse(my.Groups["index"].Value, out iy))
        {
          return ix.CompareTo(iy);
        }
      }

      return mx.Groups["year"].Value.CompareTo(my.Groups["year"].Value);
    }
  }

  class Program
  {
    static void Main(string[] args)
    {

      List<string> a = new List<string>();

      a.Add("2015");
      a.Add("2015 /Q1");
      a.Add("CY2015 /Q2");
      a.Add("2015 /Q9");
      a.Add("2015 /Q10");
      a.Add("2015 /Q11");
      a.Add("2015 /Q12");
      a.Add("2015 /Q3");
      a.Add("2014");
      a.Add("2015 /Q4");
      a.Add("2015 /Q5");
      a.Add("2015 /Q6");
      a.Add("2015 /Q7");
      a.Add("2015 /Q8");

      a.Sort(new StringComparer());

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

      Console.WriteLine("END");
      Console.ReadLine();

    }
  }

它避免了临时序列(e)。

答案 5 :(得分:-1)

您也可以轻松编写自己的此分类函数扩展名:

    public static class Extension
{
    public static List<string> sortItMyWay(this List<string> mylist)
    {
        string temp = string.Empty;

        for (int write = 0; write < mylist.Count; write++)
        {
            for (int sort = 0; sort < mylist.Count - 1; sort++)
            {
                if (mylist[sort].Weight() > mylist[sort + 1].Weight())
                {
                    temp = mylist[sort + 1];
                    mylist[sort + 1] = mylist[sort];
                    mylist[sort] = temp;
                }
            }
        }
        return mylist;
    }


public static int Weight (this string input)
{
    var value = 0;
    for (int i = input.Length - 1; i >= 0 ; i--)
    {
        value += input[i] * (int)Math.Pow(10,i);
    }
    return value;
}

}