如鹏网工作需要把如下的数组:
string[] filenames = new string[]{
"1-1编程No1.mp4",
"1-10编程No10.mp4",
"1-11编程No11.mp4",
"1-2编程No2.mp4"};
排序成如下样子:
1-1编程No1.mp4
1-2编程No2.mp4
1-10编程No10.mp4
1-11编程No11.mp4
也就是按照字符串中出现的数字的大小进行排序,当第一个不相等的数字的时候哪个数字大,则哪个数字所在的字符串就大。
如果用编程语言内置的排序算法,无论是.Net还是Java,还是其他语言,默认都是从前往后按照ASCII码的大小比较的,因此如果这样写:
string[] filenames = new string[]{
"1-1编程No1.mp4",
"1-10编程No10.mp4",
"1-11编程No11.mp4",
"1-2编程No2.mp4"};
Array.Sort(filenames);
Console.WriteLine(string.Join("\n",filenames));
那么执行结果是:
因此需要自定义比较器,在比较器中用正则表达式把字符串中的数组提取出来,然后逐个比较数字的大小。
C#代码如下,其他Java、Python等语言的思路相同:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace ConsoleApp21
{
///
/// 根据字符串中出现的数字的数字逐位比较。 "1-2 数组.2.mp3"< "1-2 数组.10.mp3"
/// "1-1 数组No.12.mp3">"1-1 数组.10.mp3"
///
class NumberPartComparer : IComparer
{
public int Compare(object x, object y)
{
string s1 = Convert.ToString(x);
string s2 = Convert.ToString(y);
int[] nums1 = ExtractNumbers(s1).ToArray();
int[] nums2 = ExtractNumbers(s2).ToArray();
//按从前向后的顺序逐位比较每一位的数字的大小
for (int i = 0; i < nums1.Length; i++)
{
//s1、s2中的数字可能个数不同
if (i < nums2.Length)
{
//如果同一位置的两个数字一样大,则继续比较后面的数字
if (nums1[i] == nums2[i])
{
continue;
}
else //如果同一位置的两个数字一样大,则“谁大谁就大”
{
return nums1[i] - nums2[i];
}
}
else//如果nums2的数字先用完,则认为x更大
{
return 1;
}
}
//如果走到这一步(比如不含有数字),则按照字符串默认比较大小
return s1.CompareTo(s2);
}
///
/// 从s字符串中按顺序取出所有出现的数字
///
///
///
public IEnumerable
{
List
var matches = Regex.Matches(s, "[0-9]+");
foreach (Match match in matches)
{
int num = Convert.ToInt32(match.Value);
results.Add(num);
}
return results;
}
}
}
如下调用:
string[] filenames = new string[]{
"1-1编程No1.mp4",
"1-10编程No10.mp4",
"1-11编程No11.mp4",
"1-2编程No2.mp4"};
Array.Sort(filenames,new NumberPartComparer());
Console.WriteLine(string.Join("\n",filenames));
执行结果如图: