Vb.net 如何显示文本文件中数字出现的频率

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

我仍在研究这些东西并一直在浏览 google 和 Youtube,但 VB.net 似乎没有这个问题我在 python 或 Java 不过。这是我必须得到的输出,但是当我读取文本文件并尝试找到频率时,它并没有像希望的那样

这是我的代码。

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

A Dictionary 提供了一个方便的实体来存储(数字,count_of_digit)数据。

然后你只需要遍历文件中的所有字符,并检查每个字符是否都是数字。如果是,则在该数字的 count_of_digit 中加一。

这是一个使用控制台应用程序的示例:

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

示例输出:

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

要在表单上使用 GetNumberFrequencies 函数,您可以:

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles btnDisplay.Click
    Dim testFile = "C:\temp\randNums.txt"
    Dim nf = GetNumberFrequencies(testFile)
    Dim sb As New Text.Stringbuilder("Digit   Frequency" & VbNewLine)

    For Each kvp As KeyValuePair(Of Integer, Integer) In nf
        sb.Append(kvp.Key & "      " & kvp.Value & VbNewLine)
    Next

    rtbshow.Text = sb.ToString()

End Sub

字典可以解决这个问题,但只要给定九个数字,索引数组也可以做到这一点,而且可能更快。

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

你可以(有点)看到它在这里工作,除了我无法让 .Net fiddle 进行字符串插值:

https://dotnetfiddle.net/FMWnMg

我们也可以通过 GroupBy() 操作来解决这个问题:

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
    rtbshow.Text = result.ToString()
End Sub

在这里查看它的工作原理:

https://dotnetfiddle.net/Xxl2z3

注意这最后会跳过缺失的数字。

File.ReadAllText returns 文件中的所有内容都是一个字符串。接下来我们声明一些变量来保存每个数字出现的次数。 .net中的一个String也是一个Char的数组。我们可以通过使用 For Each 循环来一个一个地检查文件中的每个字符来利用这一点。首先,我们用Charclass的方法检查IsDigit。如果 True 我们选择哪个 Integer 变量以 Select Case.

递增
Zero += 1

是写法的捷径

零 = 零 + 1

最后,我们写字符串来显示结果。 String 前面的 $ 表示它是一个内插字符串。您可以将变量直接插入到用大括号 { } 包围的字符串中。这取代了 String.Format 或令人眼花缭乱的引号和符号。在 Visual Studio 的最新版本中,您可以按 Enter 键来指示换行,而无需输入任何换行符。

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim FileContents = File.ReadAllText("numbers.txt")
    Dim Zero, One, Two, Three, Four, Five, Six, Seven, Eight, Nine As Integer
    For Each c In FileContents
        If Char.IsDigit(c) Then
            Select Case c
                Case "0"c
                    Zero += 1
                Case "1"c
                    One += 1
                Case "2"c
                    Two += 1
                Case "3"c
                    Three += 1
                Case "4"c
                    Four += 1
                Case "5"c
                    Five += 1
                Case "6"c
                    Six += 1
                Case "7"c
                    Seven += 1
                Case "8"c
                    Eight += 1
                Case "9"c
                    Nine += 1
            End Select
        End If
    Next
    Dim DisplayResults = $"0    {Zero}
1    {One}
2    {Two}
3    {Three}
4    {Four}
5    {Five}
6    {Six}
7    {Seven}
8    {Eight}
9    {Nine}"
    MessageBox.Show(DisplayResults)
End Sub