Lauren
Lauren

Reputation: 77

VB - How to sort a list of numbers into descending order

I'm making a frequency analysis tool for text using Visual Basic. The code below takes in an input from the user and then tells them how many of each letter appears in the text they inputted and that works fine. However, I'm struggling to order the letters into descending order.

    Dim words, output
    Dim count = 0
    Dim letters As Array = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}
    words = UCase(textInputBox.Text)
    For Each x In letters
        For Each i In words
            If x = i Then
                count = count + 1
            End If
        Next
        If count <> 0 Then
            output = output & (x & " = " & count) & vbCrLf
            textOutputBox.Text = output
            letterReplaceBox.Text = words
        End If
        count = 0
    Next
End Sub

For example, the input of the text: HELLO would output: E = 1

H = 1

L = 2

O = 1

Is there anyway I can then order these into descending order? I'm thinking of trying a two dimensional array with the letters and the numbers and then ordering from there? Or adding the numbers all to a list? Or using something like bubble sort? Or is there a more efficient way to do it? I'm not sure how to approach it...

Thank you for any suggestions or help (:

Upvotes: 2

Views: 2795

Answers (2)

Idle_Mind
Idle_Mind

Reputation: 39122

Another example to play with:

    Dim frequencies As New Dictionary(Of String, Tuple(Of String, Integer))
    For Each letter As String In textInputBox.Text.ToUpper.ToArray
        If Not frequencies.ContainsKey(letter) Then
            frequencies.Add(letter, New Tuple(Of String, Integer)(letter, 1))
        Else
            frequencies(letter) = New Tuple(Of String, Integer)(letter, frequencies(letter).Item2 + 1)
        End If
    Next

    Dim results = frequencies.Values.OrderByDescending(Function(x) x.Item2).ToList
    Dim output As New System.Text.StringBuilder
    For Each pair In results
        output.AppendLine(pair.Item1 & " = " & pair.Item2)
    Next
    textOutputBox.Text = output.ToString

Upvotes: 1

djv
djv

Reputation: 15774

Doable with LINQ. This will group your input by letter. There is some customization here. First the code:

Sub Main()
    Dim input = "The quick brown fox jumps over the lazy dog"
    Dim result =
        input.
        ToUpper().
        GroupBy(Function(c) c).
        OrderByDescending(Function(g) g.Count).
        Where(Function(g) Asc(g.First) >= 65 And Asc(g.First) <= 90).
        Select(Function(g) String.Format("'{0}' = {1}", g.First, g.Count))
    For Each r In result
        Console.WriteLine(r)
    Next
End Sub

This part of the code converts the input into uppercase (of course you could leave this out, but see the condition below which filters the letters).

ToUpper()

This is what groups by letter

GroupBy(Function(c) c)

This orders it by the number of elements

OrderByDescending(Function(g) g.Count)

This filters out anything but upper case letters (no spaces, punctuation, etc., see http://www.asciitable.com/)

Where(Function(g) Asc(g.First) >= 65 And Asc(g.First) <= 90)

This returns a formatted string with the letter and number of occurences.

Select(Function(g) String.Format("'{0}' = {1}", g.First, g.Count))

Of course, you could return anything you want but I did this for the demo.

This is the output of the code:

'O' = 4
'E' = 3
'T' = 2
'H' = 2
'U' = 2
'R' = 2
'Q' = 1
'I' = 1
'C' = 1
'K' = 1
'B' = 1
'W' = 1
'N' = 1
'F' = 1
'X' = 1
'J' = 1
'M' = 1
'P' = 1
'S' = 1
'V' = 1
'L' = 1
'A' = 1
'Z' = 1
'Y' = 1
'D' = 1
'G' = 1

Upvotes: 1

Related Questions