首页 > 解决方案 > 在 Visual Basic 中将项目从文本文件添加到多维数组

问题描述

我有这个文本文件:

Paul George|2.87|29
Stephen Curry|2.85|28
Jamal Murray|2.72|21
PJ Tucker|2.72|11
Kyle Lowry|2.61|15
Game
Paul George|g2d|g2p
Stephen Curry|g2d|g2p
Jamal Murray|g2d|g2p
PJ Tucker|g2d|g2p
Kyle Lowry|g2d|g2p
Game
Paul George|g3d|g3p
Stephen Curry|g3d|g3p
Jamal Murray|g3d|g3p
PJ Tucker|g3d|g3p
Kyle Lowry|g3d|g3p
Game
Paul George|g4d|g4p
Stephen Curry|g4d|g4p
Jamal Murray|g4d|g4p
PJ Tucker|g4d|g4p
Kyle Lowry|g4d|g4p

我想将项目添加到数组中

Names(name, gamenumber)
Distance(distance, gamenumber)
Points(Points, gamenumber)

第一个索引是玩家的数据,第二个是数据来自的游戏

例如,

distance(1, 0) = 2.87
distance(5, 0) = 2.61
distance(1, 1) = g2d

以便索引与给定游戏编号的玩家匹配。

到目前为止,我有:

Private Sub openFile_Click(sender As Object, e As EventArgs) Handles openFile.Click
    OpenFileDialog.ShowDialog()
    Dim strFileName = OpenFileDialog.FileName
    Dim objReader As New System.IO.StreamReader(strFileName)
    Dim textline As String


    Dim Names(100, 3) As String
    Dim Distance(100, 3) As String
    Dim Points(100, 3) As String

    Dim Count As Integer = 0
    Dim GameNumber As Integer = 0


    Do While objReader.Peek() <> -1

        textline = objReader.ReadLine() & vbNewLine

        If textline = "Game" Then
            GameNumber = GameNumber + 1
        Else

            Dim parts() As String = textline.Split("|")


            Names(Count, GameNumber) = parts(0)
            Distance(Count, GameNumber) = parts(1)
            Points(Count, GameNumber) = parts(2)

            Count = Count + 1

        End If
    Loop

End Sub

每行的部分由 | 分割,将它们放入“部分”,然后将从行中获得的三个部分(玩家名称、距离和点)分配到单独的数组中

Names(<Name>, 0)
Distance(<Distance>, 0)
Points(<Points>, 0)

它继续向下文本文件,但如果 line = "Game" 它应该增加 GameNumber,然后移动到下一行,继续添加数据,而不是

Names(<Name>, 1)
Distance(<Distance>, 1)
Points(<Points>, 1)

等等,但我的代码不起作用。完成这项工作后,我不会在列表框中的页面上为玩家打印所需的游戏统计信息,例如:

    For n = 0 To Count - 1
        lstNames.Items.Add(Names(n, GameWanted))
        lstNames.Items.Add(" ")
        lstDistance.Items.Add(Distance(n, GameWanted) + " Miles")
        lstDistance.Items.Add(" ")
        lstPoints.Items.Add(Points(n, GameWanted))
        lstPoints.Items.Add(" ")
    Next

标签: vb.netsortingmultidimensional-arraystreamreader

解决方案


如果您创建一个代表您的播放器的类并用字典对它们进行索引,这将变得容易得多

Class Player
  Public Property Distances as List(Of Decimal)
  Public Property Points as List(Of Integer)
  Public Property Name as String

  Public Sub New(n as String)
    Name = n
    Distances = New List(of Decimal)
    Points = New List(of Integer)
  End sub 
End class

然后在您读取文件的方法中:

Dim d as new Dictionary(of String, Person)
ForEach line as String in File.ReadAllLines(...)
  Dim bits = line.Split("|"c)
  If bits.Length < 3 Then Continue For

  If Not d.ContainsKey Then d.Add(bits(0), New Person(bits(0))

  Dim p = d(bits(0)) 'retrieve the old or just added person

  p.Distances.Add(decimal.parse(bits(1)))
  p.Points.Add(integer.parse(bits(2)))
Next line

笔记; 我是 ac# 程序员,很少再做 vb 了。我使用从 0 开始的数组索引进行编码,如果您使用 1 个基本索引,请在上面的索引中添加一个。这段代码可能应该被视为伪代码;它是从 5 年前的手机上写的 vb 的样子,可能有大量的 vb 语法错误(抱歉),或者花很长时间来做我们现在有更短的 sybtaxes 的事情(列表初始化程序等)

在遍历所有文件的循环结束时,您将拥有一本关于您的人员的字典,每个遇到的名字都有一本。每个人都会有一个分数和距离列表。如果您想将它们相加或求平均值,请向 person 类添加一个函数,该类迭代列表并返回结果,并将它们全部打印出来做一个

foreach s as string in d.Keys
  Console.Write(d(s).Name & " got avg distance " & d(s).GetAverageDist())

或类似的

打印出他们的所有距离:

foreach s as string in d.Keys
  foreach dis as decimal in d(s).Distances
    Console.Write(d(s).Name & " got distance " & dis)

这是面向对象的编程;我们使用类来模拟世界来表示事物并做有用的事情。我们不会尝试在 20 个不同的数组中收集数据并将它们与索引等联系在一起 - 这是一种非常程序化的代码思维方式,与 vb.net 的发明目的相反

实际上,这很可能没有一个适当的解决方案,而且也有点虚伪,因为我使用两个列表来跟踪距离和点并断言列表索引是相等的——索引 3 处的距离和索引 3 处的点来自游戏 4 (从零开始的索引注释)

我们真正应该做的是定义一个 GameResult 类,它具有距离、点数和游戏编号的属性,然后每个人类都有一个 List(of GameResult) - 人可以有一个函数为那个人返回一个格式很好的记分卡- 这是正确的 OO :)


推荐阅读