Fork me on GitHub

排序集合的一个小坑

  原来一直用SortList,SortedDictionary来作为键值对存储的排序集合来用,心中就默认是以key按ascall排序来存放的,在之前的案例中也没有出现问题,在最近一个demo中,打破了原来的自以为是的认识,因为在key中不但有大写小,还有特列符号。

  先看一下代码:

Console.WriteLine("-----------按ASCII排序-----------");
var chars = new char[] { 'A', '[', ']', 'a' };
foreach (var c in chars)
{
    Console.WriteLine($"{c}:{(int)c}");
}
Console.WriteLine("-----------排序集合的排序-----------");
var list = new SortedList<string, int>();
list.Add("a", 97);
list.Add("A", 65);
list.Add("[", 91);
list.Add("]", 93);
foreach (var item in list)
{
    Console.WriteLine($"{item.Key}:{item.Value}");
}

结果如下,显然SortList的key结果不是想要的按ascall排序的。

 

  那怎么才能达到按ascall呢?那就自己动手做一个排序器吧,其实就是实现IComparer<string>接口中的Compare,告诉两个string的比较规则,那自然多个数据的排序就能按这种规则给出来。当然我给的按ascall的这个规则,丝毫没有优美而言,只是能表示出意思来。

Console.WriteLine("-----------新排序集合的排序-----------");
var newList = new SortedList<string, int>(new ASCALLComparer());
newList.Add("a", 97);
newList.Add("A", 65);
newList.Add("[", 91);
newList.Add("]", 93);
foreach (var item in newList)
{
    Console.WriteLine($"{item.Key}:{item.Value}");
}

public class ASCALLComparer : IComparer<string>
{
    public int Compare(string? x, string? y)
{
        if (x == null || y == null)
        {
            throw new Exception("x or y is null");
        }
        if (x?.Length != y?.Length)
        {
            if (x?.Length < y?.Length)
            {
                for (var i = 0; i < x?.Length; i++)
                {
                    if ((int)x[i] > (int)y[i])
                    {
                        return 1;
                    }
                    else if ((int)x[i] < (int)y[i])
                    {
                        return -1;
                    }
                }
                return -1;
            }
            else
            {
                for (var i = 0; i < y?.Length; i++)
                {
                    if ((int)x[i] > (int)y[i])
                    {
                        return 1;
                    }
                    else if ((int)x[i] < (int)y[i])
                    {
                        return -1;
                    }
                }
                return 1;
            }
        }
        else
        {
            for (var i = 0; i < x?.Length; i++)
            {
                if ((int)x[i] > (int)y[i])
                {
                    return 1;
                }
                else if ((int)x[i] < (int)y[i])
                {
                    return -1;
                }
            }
            return 0;
        }
    }
}

  结果为:

 

  那原来的排序规则是什么呢?我枚举了一下ascall范围内部分可见字符,下面是正序的排序方式:

序号 符号 ascall值

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

_

-

,

;

:

!

?

.

'

"

(

)

[

]

{

}

@

*

/

\

&

#

%

`

^

+

<

=

>

|

~

$

0

1

2

3

4

5

6

7

8

9

a

A

b

B

c

C

d

D

e

E

f

F

g

G

h

H

i

I

j

J

k

K

l

L

m

M

n

N

o

O

p

P

q

Q

r

R

s

S

t

T

u

U

v

V

w

W

x

X

y

Y

z

Z

95

45

44

59

58

33

63

46

39

34

40

41

91

93

123

125

64

42

47

92

38

35

37

96

94

43

60

61

62

124

126

36

48

49

50

51

52

53

54

55

56

57

97

65

98

66

99

67

100

68

101

69

102

70

103

71

104

72

105

73

106

74

107

75

108

76

109

77

110

78

111

79

112

80

113

81

114

82

115

83

116

84

117

85

118

86

119

87

120

88

121

89

122

90

 

  想要更快更方便的了解相关知识,可以关注微信公众号 
 

 

 

posted @ 2022-03-18 21:16  桂素伟  阅读(38)  评论(0编辑  收藏  举报