Metalcat
Metalcat

Reputation: 43

Adding items to a multidimensional array from a textfile in Visual Basic

I have this textfile:

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

I want to add the items to the arrays

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

with the first index being the data for the player, and the second being the game that data is from

For example,

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

So that the indexes match up with the player for the given game number.

So far I have:

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

The parts of each line are split up by |, putting them into "parts", it then assigns the three parts it gets from the line (the player name, distance, and points) into there separate arrays as

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

It continues down the textfile but IF the line = "Game" it should, increment GameNumber, and then move to the next line, continuing to add the data, instead as

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

and so on, but it my code isn't working. After getting this working, I wont it to print the desired Game statistics for the players on the page in a listbox with something like:

    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

Upvotes: 1

Views: 51

Answers (1)

Caius Jard
Caius Jard

Reputation: 74615

This would become a lot easier if you create a class representing your player and index them with a dictionary

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

And then in your method that reads your file:

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

Note; I'm a c# programmer and seldom do vb any more. I code with array indexes starting at 0, if you're on 1 base indexing, add one to the indexes above. This code should probably be treated as pseudocode; it was written on a cellphone from a 5 year old memory of what vb looks like and might have a raft of vb syntax errors(sorry) or take the long way round to do things that we have shorter sybtaxes for these days (list initializers etc)

At the end of this loop through all the file you will have a dictionary of your people, one per name encountered. Each person will have a list of scores and distances. If you want to add them up or average them add a Function to person class that iterates the list and returns the result, and to print them all out do a

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

Or similar

To print out all their distances:

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

This is object oriented programming; we model the world using classes to represent things and do useful stuff. We don't try to collect data together in 20 different arrays and tie it all together with indexes etc - that's a very procedural code mindset and the opposite of what vb.net was invented for

It's likely actually that this falls short of a proper solution and is also somewhat hypocritical because I use two lists to track distance and points and assert that the list indexes are equal - the distance at index 3 and the points at index 3 are from game 4 (zero based indexing note)

What we really should do is also define a GameResult class and it have properties of distance, points and gamenumber, then each person class has a single List(of GameResult) - person could have a function that returns a nicely formatted score card for that person - that's proper OO :)

Upvotes: 1

Related Questions