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