Home > Net >  Vb.net how to display the frequency of digits from a text file
Vb.net how to display the frequency of digits from a text file

Time:12-09

I am still studying this stuff and been looking through google and Youtube but there doesn't seem to have this problem for VB.net I saw some on python or Java though. This is the output that I have to get but when i read the text file and try to find the frequency its doesn't go as hoped

enter image description here

This is my code.

enter image description here

Imports System.IO
Public Class Form1
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles btnDisplay.Click

        Dim reader As TextReader = New StreamReader("number.txt")
        Dim num As Integer = 0

        For Each item In reader.ReadToEnd
            If item.CompareTo(reader.ReadLine) = True Then
                num  = 1
            End If

        Next

        rtbshow.Text = "Digit" & " " & " " & " Frequency " & vbNewLine & reader.ReadToEnd() & " " & " " & num

    End Sub
End Class

CodePudding user response:

A Dictionary provides a convenient entity to store the (digit, count_of_digit) data.

Then you just need to go through all the characters in the file and check if each one is a digit. If it is, then add one to the count_of_digit for that digit.

This is an example using a Console Application:

Imports System.IO

Module Module1

    Sub CreateTestFile(s As String)
        Dim rand As New Random()

        Using sw As New StreamWriter(s)
            For i = 1 To 10000
                sw.Write(rand.Next(0, 10).ToString())
            Next
        End Using

    End Sub

    Function GetNumberFrequencies(s As String) As Dictionary(Of Integer, Integer)
        Dim nf As New Dictionary(Of Integer, Integer)
        For i = 0 To 9
            nf.Add(i, 0)
        Next

        Using sr As New StreamReader(s)
            While Not sr.EndOfStream
                Dim line = sr.ReadLine()
                For Each c In line
                    If c >= "0" AndAlso c <= "9" Then
                        ' A quick way to convert the strings "0"-"9" to the numbers 0-9:
                        Dim index = AscW(c) - AscW("0)")
                        nf(index)  = 1
                    End If
                Next
            End While
        End Using

        Return nf

    End Function

    Sub Main()
        ' Always specify a full path to a file that you use.
        Dim testFile = "C:\temp\randNums.txt"
        CreateTestFile(testFile)
        Dim nf = GetNumberFrequencies(testFile)

        For Each kvp As KeyValuePair(Of Integer, Integer) In nf
            Console.WriteLine(kvp.Key & " - " & kvp.Value)
        Next

        Console.ReadLine()

    End Sub

End Module

Sample output:

0 - 1013
1 - 963
2 - 991
3 - 1033
4 - 1001
5 - 966
6 - 962
7 - 1006
8 - 1018
9 - 1047

CodePudding user response:

A dictionary can work for this, but given just the nine digits an indexed array can do just as well and probably be faster.

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles btnDisplay.Click
    Dim digitCounts = Enumerable.Repeat(0,10).ToArray()

    Dim digits = File.ReadAllText("number.txt").
                   Where(Function(c) Char.IsDigit(c)).
                   Select(Function(c) Asc(c) - Asc("0"c))
    For Each d As Integer In digits
        digitCounts(d)  = 1
    Next
    Dim result As New StringBuilder($"Digit{vbTab}Frequency{vbCrLf}")
    For i As Integer = 0 To 9
        result.AppendLine($"{i,3}{vbTab}{digitCounts(i),7}")
    Next
    rtbshow.Text = result.ToString()
End Sub

You can (kind of) see it working here, except I couldn't get .Net fiddle to do the string interpolation:

https://dotnetfiddle.net/FMWnMg

We could also solve this with a GroupBy() operation:

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles btnDisplay.Click
    Dim result As New StringBuilder($"Digit{vbTab}Frequency{vbCrLf}")
    Dim digits = File.ReadAllText("number.txt").
             Where(Function(c) Char.IsDigit(c)).
             OrderBy(Function(d) d).
             GroupBy(Function(d) d, 
                     Function(d, g) $"{d,3}{vbTab}{g.Count(),7}{vbCrLf}"
             )
    
    For Each d As String in digits
        result.Append(d)
    Next
    Console.WriteLine(result.ToString()
End Sub

See it work here:

https://dotnetfiddle.net/Xxl2z3

Note this last skips missing digits.

  • Related