Reputation: 77
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
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
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