【发布时间】:2018-09-24 15:16:10
【问题描述】:
我有一个复杂的排序模式要复制,我的解决方案似乎有点笨拙。 我的输入是一个数字列表,可以有几个字母作为后缀,前缀都是字母('aaa'、'aab'、'ac' 等)。 我需要按数字排序,然后按后缀(如果有的话)排序,然后按前缀(如果有的话)。
例如
"a1a",
"5ac",
"1",
"12",
"2",
"11",
"5aa",
"3",
"5ab",
"a2b",
"abb11ca",
"1b",
"aba11ca"
将被排序为
1
a1a
1b
2
a2b
3
5aa
5ab
5ac
11
aba11ca
abb11ca
12
这是我使用 Linq 提出的解决方案。
static void Main(string[] args)
{
var arr = new []
{"b2","a1a","5ac","1","12","2","11","5aa","3","5ab","a1","a2b","abb11ca","1b","aba11ca"
};
var ordered = arr.Select(str => {
var parts = SplitIntoPrefixNumberSuffix(str);
var number = int.Parse(parts[1]);
return new { str, parts, number };
})
.OrderBy(x => x.number).ThenBy(x => x.parts[2]).ThenBy(x => x.parts[0])
.Select(x => x.str);
Console.WriteLine("sorted array: ");
foreach (var s in ordered)
{
Console.WriteLine("{0}", s);
}
Console.ReadLine();
}
public static string[] SplitIntoPrefixNumberSuffix(string str)
{
var numChar = new[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
var numLoc = str.IndexOfAny(numChar);
var nums = "";
foreach (var c in str)
{
if (char.IsDigit(c))
nums = nums + c;
}
Console.WriteLine("numLoc: {0}; nums: {1}", numLoc, nums.Count());
var prefix = str.Substring(0, numLoc);
var suffix = str.Substring(numLoc + nums.Count());
Console.WriteLine("prefix {0}; nums {1}; suffix {2}", prefix, nums, suffix);
return new[] { prefix, nums, suffix };
}
这是一个工作的 .netfiddle:https://dotnetfiddle.net/C7ZA0b。
虽然它有效,但感觉这不是一个很好的解决方案。我对集合进行了多次迭代,我认为我应该使用自定义的可比较对象。
我以前从未写过 Comparable;我查看了Dot Net Pearls Alphanumeric Sorting 并且可以按照它进行操作,但还不足以对其进行修改以满足我的需要。
我可以使用 IComparable 来完成上述工作吗?有什么学习写作的好地方的建议吗?
【问题讨论】:
-
请定义“前缀”和“后缀”。
-
“ab11c22d”如何工作?
-
我数不清我说过“这不是一个很好的解决方案”的次数,但还是检查了代码。如果它有效,那么为什么还要将逻辑移植到
IComparable?老实说,我认为您不会因此而获得任何收益。请务必编写一些单元测试以使其正常工作。 -
前缀和后缀都是字母,在“中心”数值上添加和添加。我会更新我的问题以澄清。
-
"b2" 在您的示例中丢失。