如鵬網(wǎng)工作需要把如下的數(shù)組:
string[] filenames = new string[]{
"1-1編程N(yùn)o1.mp4",
"1-10編程N(yùn)o10.mp4",
"1-11編程N(yùn)o11.mp4",
"1-2編程N(yùn)o2.mp4"};
排序成如下樣子:
1-1編程N(yùn)o1.mp4
1-2編程N(yùn)o2.mp4
1-10編程N(yùn)o10.mp4
1-11編程N(yùn)o11.mp4
也就是按照字符串中出現(xiàn)的數(shù)字的大小進(jìn)行排序咖楣,當(dāng)?shù)谝粋€(gè)不相等的數(shù)字的時(shí)候哪個(gè)數(shù)字大,則哪個(gè)數(shù)字所在的字符串就大骨杂。
如果用編程語(yǔ)言內(nèi)置的排序算法账嚎,無(wú)論是.Net還是Java莫瞬,還是其他語(yǔ)言,默認(rèn)都是從前往后按照ASCII碼的大小比較的郭蕉,因此如果這樣寫(xiě):
string[] filenames = new string[]{
"1-1編程N(yùn)o1.mp4",
"1-10編程N(yùn)o10.mp4",
"1-11編程N(yùn)o11.mp4",
"1-2編程N(yùn)o2.mp4"};
Array.Sort(filenames);
Console.WriteLine(string.Join("\n",filenames));
那么執(zhí)行結(jié)果是:
因此需要自定義比較器疼邀,在比較器中用正則表達(dá)式把字符串中的數(shù)組提取出來(lái),然后逐個(gè)比較數(shù)字的大小召锈。
C#代碼如下旁振,其他Java、Python等語(yǔ)言的思路相同:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace ConsoleApp21
{
? ? /// <summary>
? ? /// 根據(jù)字符串中出現(xiàn)的數(shù)字的數(shù)字逐位比較涨岁。 "1-2 數(shù)組.2.mp3"< "1-2? 數(shù)組.10.mp3"
? ? /// "1-1 數(shù)組No.12.mp3">"1-1 數(shù)組.10.mp3"
? ? /// </summary>
? ? 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();
? ? ? ? ? ? //按從前向后的順序逐位比較每一位的數(shù)字的大小
? ? ? ? ? ? for (int i = 0; i < nums1.Length; i++)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? //s1拐袜、s2中的數(shù)字可能個(gè)數(shù)不同
? ? ? ? ? ? ? ? if (i < nums2.Length)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? //如果同一位置的兩個(gè)數(shù)字一樣大瞬项,則繼續(xù)比較后面的數(shù)字
? ? ? ? ? ? ? ? ? ? if (nums1[i] == nums2[i])
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? continue;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? else //如果同一位置的兩個(gè)數(shù)字一樣大摄狱,則“誰(shuí)大誰(shuí)就大”
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? return nums1[i] - nums2[i];
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? else//如果nums2的數(shù)字先用完症概,則認(rèn)為x更大
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? return 1;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? //如果走到這一步(比如不含有數(shù)字)蛔钙,則按照字符串默認(rèn)比較大小
? ? ? ? ? ? return s1.CompareTo(s2);
? ? ? ? }
? ? ? ? /// <summary>
? ? ? ? /// 從s字符串中按順序取出所有出現(xiàn)的數(shù)字
? ? ? ? /// </summary>
? ? ? ? /// <param name="s"></param>
? ? ? ? /// <returns></returns>
? ? ? ? public IEnumerable<int> ExtractNumbers(string s)
? ? ? ? {
? ? ? ? ? ? List<int> results = new List<int>();
? ? ? ? ? ? var matches = Regex.Matches(s, "[0-9]+");
? ? ? ? ? ? foreach (Match match in matches)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? int num = Convert.ToInt32(match.Value);
? ? ? ? ? ? ? ? results.Add(num);
? ? ? ? ? ? }
? ? ? ? ? ? return results;
? ? ? ? }
? ? }
}
如下調(diào)用:
string[] filenames = new string[]{
"1-1編程N(yùn)o1.mp4",
"1-10編程N(yùn)o10.mp4",
"1-11編程N(yùn)o11.mp4",
"1-2編程N(yùn)o2.mp4"};
Array.Sort(filenames,new NumberPartComparer());
Console.WriteLine(string.Join("\n",filenames));
執(zhí)行結(jié)果如圖: