Changes in the C# language allow us to write more concise code than ever before, and it’s fun to see what solutions developers write. In this short but fun post, I’ll be writing a method that takes in an `int`

and converts it into its ordinal position, the kind of output you might see on a leaderboard. So, for example, the value of `1`

would be `1st`

, the value of `2`

is `2nd`

, and so on.

# The Ranking Problem

Given we have a collection of integers, we want to convert those values into their human-readable ordinal values. In English, we describe position using the suffixes of `st`

, `nd`

, `rd`

, and `th`

. So, for example, a collection of integers containing the values of `1, 2, 3, 4`

would be equivalent to `1st, 2nd, 3rd, 4th`

. There are a few rules to keep in mind when dealing with numbers and their possible suffixes:

- When a value of
`1`

is in the position of the one whole number part, it will have a suffix of`st`

unless the value in the tens whole-number part is`11`

; in that case, the suffix is`th`

. - When a value of
`2`

is in the position of the one whole number part, it will have a suffix of`nd`

unless the value in the tens whole-number part is`12`

; in that case, the suffix is`th`

. - When a value of
`3`

is in the position of the one whole number part, it will have a suffix of`rd`

unless the value in the tens whole-number part is`13`

; in that case, the suffix is`th`

. - In all other scenarios, the suffix will be
`th`

.

In general, the only numbers we should be cautious about are the ones that end in `1`

, `2`

, `3`

, `11`

, `12`

, and `13`

. We may treat all other numbers the same with the `th`

suffix.

Let’s write some code.

## Using Pattern Matching For Pretty Output

Given our rules, we can use C#’s pattern matching to define our rules around a provided `int`

value. Our first step is to get the whole number part of our integer, and we can do that by using the remainder operator.

```
var ones = value % 10;
var tens = value % 100;
```

Now that we know the whole-number parts of our integer value, we can write our pattern matching switch statement.

```
var suffix = ones switch {
1 when tens != 11 => "st",
2 when tens != 12 => "nd",
3 when tens != 13 => "rd",
_ => "th"
};
```

Now, let’s put it all together. The method should be straightforward to implement from here.

```
string Ranking(int value)
{
var ones = value % 10;
var tens = value % 100;
var suffix = ones switch {
1 when tens != 11 => "st",
2 when tens != 12 => "nd",
3 when tens != 13 => "rd",
_ => "th"
};
return string.Concat(value.ToString("N0"), suffix);
}
```

I end up using the string formatter of `N0`

to format the integer with zero (0) decimal placeholders. Let’s run the method in a console application.

```
using static System.Console;
using static System.String;
string Ranking(int value)
{
var ones = value % 10;
var tens = value % 100;
var suffix = ones switch {
1 when tens != 11 => "st",
2 when tens != 12 => "nd",
3 when tens != 13 => "rd",
_ => "th"
};
return Concat(value.ToString("N0"), suffix);
}
var low = new List<int> { 1, 2, 3, 4, 11 }.Select(Ranking);
var high = new[] {1_001, 1_002, 1_003, 1_004, 1_011 }.Select(Ranking);
WriteLine($"First collection: {Join(", ", low) }");
WriteLine($"Second collection: {Join(", ", high)}");
```

Writing the app, we get the following application output.

```
First collection: 1st, 2nd, 3rd, 4th, 11th
Second collection: 1,001st, 1,002nd, 1,003rd, 1,004th, 1,011th
```

Neat! I hope you enjoyed this short post about C# pattern matching, and let me know if you think you could improve it by reaching me on Twitter @buhakmeh. Thanks for reading my posts and sharing them with friends and colleagues.