按字母顺序排列,Array.Sort()不能正常工作

时间:2019-08-29 19:31:29

标签: c# .net

我对字母顺序有疑问。在我的情况下,Array.Sort()不能很好地工作。

string str = "AaBbCc";
char[] arr = second.ToCharArray();
Array.Sort(arr);

// Output: ABCabc
// I need: AaBbCc

有什么想法吗?

3 个答案:

答案 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-90A-Z,小写(97-122)为a-z

假设您始终希望大写字母位于小写字母之前,我们可以使用一些技巧在比较之前通过从ASCII值中减去31.5来对小写字母进行排序。

通过这样做,a变为65.597 - 31.5),并将在A65)和B({ {1}})。其他所有小写字母也是如此。这样可以避免创建一堆新字符串进行比较和进行多次排序的费用。

例如:

66

输出:

enter image description here

答案 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"