Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 对字符串列表进行数字排序_C#_Linq_List_Sorting - Fatal编程技术网

C# 对字符串列表进行数字排序

C# 对字符串列表进行数字排序,c#,linq,list,sorting,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");

我有以下字符串列表:

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");
但是我如何修改它使其看起来像下面这样呢

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等。

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

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;

您还可以轻松编写自己的排序函数扩展:

    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;
}
公共静态类扩展
{
公共静态列表sortItMyWay(此列表mylist)
{
字符串温度=字符串为空;
for(int write=0;writemylist[sort+1].Weight())
{
temp=mylist[sort+1];
mylist[sort+1]=mylist[sort];
mylist[排序]=温度;
}
}
}
返回mylist;
}
公共静态整数权重(此字符串输入)
{
var值=0;
对于(int i=input.Length-1;i>=0;i--)
{
值+=输入[i]*(int)数学功率(10,i);
}
返回值;
}
}这篇文章和你的相似。根据您的要求进行编辑:

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'));
}
我这样做:

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 2015 2015/M1 2015年/平方米 2015/M3 2015/M4 2015/M5 2015/M6 2015/M7 2015/M8 2015/M9 2015/M10 2015/M11 2015/M12
我详细阐述了Niyoko Yuliawan的解决方案,结果是:

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

    }
  }
类StringComparer:IComparer
{
常量字符串模式=@“^\D*(?\D{4})(\/[MQ](?\D+)))?$”;
公共整数比较(字符串x、字符串y)
{
var mx=Regex.Match(x,模式);
var my=Regex.Match(y,模式);
int ix;
if(int.TryParse(mx.Groups[“index”].Value,out ix))
{
国际;
if(int.TryParse(my.Groups[“index”].Value,out iy))
{
返回ix.CompareTo(iy);
}
}
返回mx.Groups[“year”].Value.CompareTo(my.Groups[“year”].Value);
}
}
班级计划
{
静态void Main(字符串[]参数)
{
列表a=新列表();
a、 添加(“2015”);
a、 添加(“2015/Q1”);
a、 添加(“2015年第二季度”);
a、 添加(“2015/Q9”);
a、 添加(“2015/Q10”);
a、 添加(“2015/Q11”);
a、 添加(“2015/Q12”);
a、 添加(“2015/Q3”);
a、 添加(“2014”);
a、 添加(“2015/Q4”);
a、 添加(“2015/Q5”);
a、 添加(“2015/Q6”);
a、 添加(“2015/Q7”);
a、 添加(“2015/Q8”);
a、 排序(新StringComparer());
foreach(a中的变量x)
{
控制台写入线(x);
}
控制台。写入线(“结束”);
Console.ReadLine();
}
}
它避免了临时序列(e)。

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

实现IComparer接口,执行自定义排序算法,并将其传递给排序方法。MSDN是您的朋友。您的输入格式是否总是“yyyy X/MM”,其中yyy是年,X是任意随机字符,MM是月?您的问题的简短答案是按int排序,而不是按字符串排序。我需要在字符串列表中进行排序,因为我有2015 Q/1,2015 Q/2,这些值也是动态创建的。如果要将2015 Q/1与2015 M/1排序为同一字符串,该怎么办?@Asim您希望/Q1在/M1之后还是在/M3之后排序?@NiyokoYuliawan我已经测试了您的方法,它解决了月份问题,我可以修改它以使其也适用于Q/1吗?@NiyokoYuliawan谢谢,我如何修改它以在开始时添加CY或FY,如CY2015/M1。在整个字符串中为CY或FY。Thanks@Asim将正则表达式模式更改为
^[A-Za-z]*\d+(?:\/[MQ](\d+))$
。这如何回答问题?这是按字符串长度进行有效排序的方法?如果字符串太长(由于'Math.Pow'的原因),它将失败。这根本不是一个显而易见的解决办法。你能解释一下吗?这个权重函数给每个字符串一个int值。这不是按长度排序!关于长度的限制你是对的,但这个问题没有问题。这种扩展可能不是最佳实践,但是提问者可以按照自己喜欢的方式改变权重函数,对于这个问题以及其他他喜欢的排序方式。在我看来,这比复制正则表达式有更高的学习效果,而不了解它是如何工作的。sortItMyWay函数只是一个冒泡排序,使用权重函数。
  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();

    }
  }