我对字母顺序有疑问。在我的情况下,Array.Sort()不能很好地工作。
string str = "AaBbCc";
char[] arr = second.ToCharArray();
Array.Sort(arr);
// Output: ABCabc
// I need: AaBbCc
有什么想法吗?
答案 0 :(得分:6)
您可以使用LINQ实现所需的功能。
首先,我们需要将您的字符分成一系列单个字符串。我们可以使用select来做到这一点。
str.Select(x => x.ToString())
好的,现在我们要订购此列表。字符串的默认排序是单词排序,它会像aAbBcC
一样排序。由于您想先获取大写字母,因此我们将使用OrdinalIgnoreCase
比较器,它将字符分组。
.OrderBy(x => x, StringComparer.OrdinalIgnoreCase)
好的,所以我们现在将字符分组。现在,我们通常要使用ThenBy对这些组进行排序,以使首位大写。
.ThenBy(x => x, StringComparer.Ordinal)
最后,我们可以将其转换为数组。
.ToArray();
将其组合在一起,我们得到以下信息:
var res = str.Select(x => x.ToString())
.OrderBy(x => x, StringComparer.OrdinalIgnoreCase)
.ThenBy(x => x, StringComparer.Ordinal)
.ToArray();
哪个给了我们一个看起来像这样的数组:["A","a","B","b","C","c"]
在这一点上,正如@dvo所指出的,我们可以通过调用String.Join将其返回为单个字符串,如下所示:
var resStr = string.Join("", res);
正如@RufusL指出的那样,我们可以为该查询做更多的事情。由于我们知道最终需要一个字符串,因此我们可以完全跳过ToArray
调用并坚持使用IOrderedEnumerable<string>
。
var res = str.Select(x => x.ToString())
.OrderBy(x => x, StringComparer.OrdinalIgnoreCase)
.ThenBy(x => x, StringComparer.Ordinal);
由于我们不使用字符串连接任何内容,因此可以使用string.Concat
代替string.Join
。
var resStr = string.Concat(res);
答案 1 :(得分:1)
问题是您的代码按ASCII值排序,大写(65-90
为A-Z
,小写(97-122
)为a-z
。
假设您始终希望大写字母位于小写字母之前,我们可以使用一些技巧在比较之前通过从ASCII值中减去31.5
来对小写字母进行排序。
通过这样做,a
变为65.5
(97 - 31.5
),并将在A
(65
)和B
({ {1}})。其他所有小写字母也是如此。这样可以避免创建一堆新字符串进行比较和进行多次排序的费用。
例如:
66
输出:
答案 2 :(得分:0)
还有一种解决方案,不需要对ASCII值进行数学运算:我们可以首先对字符进行排序,以使每个字符的大写和小写字母彼此相邻,方法是使用OrderBy(char.ToLower)
(按小写字符的ASCII值排序),然后我们可以按char.IsLower
对它们进行排序,然后对小写字符排序,将大写字符排在后面:
string str = "zZYyabCABcxX";
string ordered = string.Concat(str.OrderBy(char.ToLower).ThenBy(char.IsLower));
// ordered == "AaBbCcXxYyZz"