# Finding The Second Lowest Item In A List Using C# and F#

October 02, 2015I cam across an interesting problem where I needed to find the **second** lowest item in a list. You may think this is a simple problem with a simple solution:

Sort the list in ascending order, and take the second item from the list. Done! (Mic Drop)

The knee-jerk solution described above would work for a list of unique items, but not for a list where items could have the same value. Here is the solution I came up with. Additionally, we also want to get the second lowest when the list may only have one value. A list of one item is naturally always the first, second, third, and so-on lowest.

## Logic

The solution I came up with actually has **six** steps. I will describe each step and show what the results would be at each of those steps.

### Working Set

Before we can start, lets define a data set that will be reduced as we apply our functions.

```
// The Dataset
[ 1, 1, 2, 2, 3, 3]
```

### Step 1 : Grouping Like Items

The first and most important step is to group like items. Let's see what our dataset would look like.

```
// after grouping
[ 1, 1 ]
[ 2, 2 ]
[ 3, 3 ]
```

### Step 2 : Ordering

We need to order the value by **ascending** order. That means we have our grouped items from lowest to highest.

```
// Ordered
[ 1, 1 ]
[ 2, 2 ]
[ 3, 3 ]
```

Lucky for us, it seems our dataset was already ordered.

### Step 3 : Take Two Collections

We need to take the first two items, since we are looking for the **second** lowest. We know that are target value exists from 1..N, N being the number of places.

```
[ 1, 1 ]
[ 2, 2 ]
```

### Step 4 : Reverse

Now we know we have at most two collections, where the potentially the last collection has similar values for the second lowest value. Reversing our collection will make it the first in the list of collections.

```
[ 2, 2 ]
[ 1, 1 ]
```

## Step 5: Take One Collection

Now let's narrow down our result to the collection of answers.

```
[ 2, 2 ]
```

## Step 6 : Reduce To One Value

Now that we have one collection, let's pull the first value from it.

```
2
```

There you have it. We found our solution! Some of these steps can be switched around if you are looking for value types, but I recommend following these steps if you are trying to use this approach to find a more complex object that fits this criteria. Now let's look at the implementation in C# and F#.

## C# Solution

You can try the C# solution here: https://dotnetfiddle.net/piHF7J

```
using System;
using System.Linq;
var numbers = new [] {
1, 1,
2, 2,
3, 3,
4, 4, 4,
5, 5, 5
};
var result =
numbers
.GroupBy(x => x)
.OrderBy(g => g.Key)
// take the bottom two
.Take(2)
// reverse so the second lowest is first
.Reverse()
// take the second lowest
.Take(1)
// select the first plan
.Select(x => x.FirstOrDefault())
// select the first result
.FirstOrDefault();
Console.WriteLine("The second lowest is : {0}", result);
```

When executed our result is:

The second lowest is : 2

## F# Solution

The F# solution is just as simple, but I have to admit I am still an F# novice and there may be a better way to do this. You can run this sample here: https://dotnetfiddle.net/NeGxn5

```
using
let numbers =
[
1; 1;
2;
3; 3; 3;
4; 4;
5; 5;
];
let result =
numbers
|> Seq.groupBy (fun x -> x)
|> Seq.sortBy (fun (k,v) -> k)
|> Seq.take 2
|> Seq.toList
|> List.rev
|> Seq.head
|> fun (k,v) -> v
|> Seq.head
printfn "The second lowest is %A" result
```

When executed, we get the following result.

The second lowest is : 2

## Conclusion

I have to admit this was a fun problem to solve, as the simple *"answer"* that I described at first may be a lot of developer's first inclination. To solve this problem, I sat down with a sheet of paper and walked through each step. I found that it was easier to rationalize the problem when I didn't have to deal with an IDE or language quirk. I hope you found this post fun, and let me know what you think or if I could do something better.