i have an array which has a name and a score next to it, i need it to be sorted high to low. i already have it sorted alphabetically.
Dim reply3 As String
Dim name As String
Dim score As Integer = 0
Dim classnum As Integer
Dim filePath As String
Dim reply As Integer
Dim reply2 As Integer
Dim strline As String
Dim array() As String
Sub Main()
Console.Title = "Math Test"
Console.WriteLine("Do you want to start the test or view previous results? Press 1 for test, 2 for results")
reply = Console.ReadLine
If reply > 2 Then
MsgBox("Invalid Reply Press Ok to end")
End
End If
If reply = 2 Then
Console.WriteLine("What class do you want to see the results of? 1, 2, or 3?")
reply2 = Console.ReadLine()
End If
If reply2 > 3 Then
MsgBox("Invalid Reply Press Ok to exit")
End
End If
Select Case reply2
Case 1
Dim results1 As String = File.ReadAllText("Z:\scores class 1.txt")
array = Split(results1, "-")
For i As Integer = 0 To array.Length - 1
Console.WriteLine(array(i))
Next
Console.WriteLine("Would you like these to be sorted? Press 1 for yes, 2 for no")
If Console.ReadLine = 1 Then
System.Array.Sort(array)
For i As Integer = 0 To array.Length - 1
Console.WriteLine(array(i))
Next
ElseIf Console.ReadLine = 2 Then
End
End If
Console.ReadLine()
Case 2
Dim results1 As String = File.ReadAllText("Z:\scores class 2.txt")
array = Split(results1, "-")
For i As Integer = 0 To array.Length - 1
Console.WriteLine(array(i))
Next
Console.WriteLine("Would you like these to be sorted? Press 1 for yes, 2 for no")
If Console.ReadLine = 1 Then
System.Array.Sort(array)
For i As Integer = 0 To array.Length - 1
Console.WriteLine(array(i))
Next
ElseIf Console.ReadLine = 2 Then
End
End If
Console.ReadLine()
Case 3
Dim results1 As String = File.ReadAllText("Z:\scores class 3.txt")
array = Split(results1, "-")
For i As Integer = 0 To array.Length - 1
Console.WriteLine(array(i))
Next
Console.WriteLine("Would you like these to be sorted? Press 1 for yes, 2 for no")
If Console.ReadLine = 1 Then
System.Array.Sort(array)
For i As Integer = 0 To array.Length - 1
Console.WriteLine(array(i))
Next
ElseIf Console.ReadLine = 2 Then
End
End If
Console.ReadLine()
End Select
If reply = 1 Then
Console.WriteLine("What is your name?")
name = Console.ReadLine
Console.WriteLine("What class are you in, 1, 2 or 3?")
classnum = Console.ReadLine
If classnum < 1 Then
MsgBox("Invalid Class number")
End
ElseIf classnum > 3 Then
MsgBox("Invalid Class number")
End
End If
Console.WriteLine("What is 9+10 ?")
If Console.ReadLine = 19 Then
score += 1
End If
Console.WriteLine("What is 5x10 ?")
If Console.ReadLine = 50 Then
score += 1
End If
Console.WriteLine("What is 122÷2 ?")
If Console.ReadLine = 61 Then
score += 1
End If
Console.WriteLine("What is 424 + 10 ?")
If Console.ReadLine = 434 Then
score += 1
End If
Console.WriteLine("What is 234 x 3 ?")
If Console.ReadLine = 702 Then
score += 1
End If
Console.WriteLine("What is 10 x 10 ?")
If Console.ReadLine = 100 Then
score += 1
End If
Console.WriteLine("What is 12 x 64 ?")
If Console.ReadLine = 768 Then
score += 1
End If
Console.WriteLine("What is the value of N in this equation? 2n+6=10?")
If Console.ReadLine = 4 Then
score += 1
End If
Console.WriteLine("What is 9 x 73 ?")
If Console.ReadLine = 657 Then
score += 1
End If
Console.WriteLine("What is 1 + 1 ?")
If Console.ReadLine = 2 Then
score += 1
End If
MsgBox("Your score was " & score & " Click ok to finish.")
Dim output1 As String = name & " " & score & "-"
Select Case classnum
Case 1
filePath = System.IO.Path.Combine(
My.Computer.FileSystem.SpecialDirectories.MyDocuments, "scores class 1.txt")
My.Computer.FileSystem.WriteAllText(filePath, output1, True)
Case 2
filePath = System.IO.Path.Combine(
My.Computer.FileSystem.SpecialDirectories.MyDocuments, "scores class 2.txt")
My.Computer.FileSystem.WriteAllText(filePath, output1, True)
Case 3
filePath = System.IO.Path.Combine(
My.Computer.FileSystem.SpecialDirectories.MyDocuments, "scores class 3.txt")
My.Computer.FileSystem.WriteAllText(filePath, output1, True)
End Select
End If
End Sub
I need the array called array to be sorted numerically. i will add the option for the user to choose if he/she wants further sorting after it has been done alphabetically.
Strings are not numbers. They are text.
In string format, they are simply characters ( numerals ) and they do not and will not sort numerically:
Dim myVals As String() = {"5", "07", "178", "9", "899", "42", "3"}
' add two of the "numbers"
Console.WriteLine("{0} + {1} = {2}", myVals(0),
myVals(1), (myVals(0) + myVals(1)))
Array.Sort(myVals)
Array.Reverse(myVals)
For Each s As String In myVals
Console.Write("{0} ", s)
Next
Output:
5 + 07 = 507
9 899 5 42 3 178 07
The values do not add as expected, because they are not numbers. Instead, the code simply concatenates (glues together) two bits of string. The array contents sort as characters also. When sorting, "9"
will always be seen as larger than the others.
This applies to dates stored as strings as well. "9/16/1914" will always evaluate larger/later than "12/1/2015".
Because as text, the lexicographical or alphabetical order used (0,1,2,3,4,5,6,7,8,9).
Stored as string, numbers loose their numeric value (until converted). "9"
sorts higher than "899"
because "9"
is higher than "899"
. The same way that "Able" and "Baker" will sort based on "A" and "B". The "07"
sorts lowest because of the zed. The numerical value is ignored because they are strings (text).
The same is true for string "dates" - they are not dates and have no date value. Your brain interprets them as dates based on the pattern; to the computer, they remain text and "9/16/yyyy"
will evaluate larger than "12/1/yyyy"
.
We now know that there are no integers in string arrays, just numerals. But also, if you have 2 pieces of data, you need to store them separately if you want to use them individually. A Class is ideal for this:
Public Class Student
Public Property Name As String
Public Property Score As Integer
Public Sub New()
End Sub
' overload
Public Sub New(n As String, s As Integer)
Name = n
Score = s
End Sub
Public Overrides Function ToString() As String
Return String.Format("{0} ({1})", Name, Score)
End Function
End Class
Notice that the name and score are stored as the correct data type which will allow code to use the Score as a numeric value. Unlike using 2 arrays, the name cannot become detached from the score.
Note also that ToString()
allows us to display the data however we want. Just because we want to show the name and score together does not mean we must glue that information together. Sample output:
Charlie (89)
Give up your arrays (and ArrayLists)! It is the 21st Century and we have Typed collections (called Generics ):
Private Students As List(of Student) ' declaration
Students
is a collection which can only store Student
objects, which in turn contains 2 pieces of data. Let's add some:
Students = New List(Of Student) ' create List instance
Dim stud As New Student ' create new student
stud.Name = "Harvey" ' set props
stud.Score = 72 ' 72 is a NUMBER
Students.Add(stud) ' add to collection
' fast way, using the overload, no temp student object needed
Students.Add(New Student("Bob", 67))
Students.Add(New Student("Hoover", 82))
Students.Add(New Student("Ziggy", 97))
...
Students.Add(New Student("Zoey", 89))
Note that we do not have to set the size of the List(of Student)
- it grows as it needs to. You can still reference them by element/position: Students(0)
is a Student
object, and Students(0).Name
will be the name of the student in the first slot ("Harvey").
Students = Students.OrderByDescending(Function(x) x.Score).ToList()
This creates a new collection in the desired order. To sort matching scores by name:
Students = Students.OrderByDescending(Function(x) x.Score).
ThenBy(Function(q) q.Name).ToList()
' print the contents:
For Each st As Student In Students
Console.WriteLine(st)
Next
The result after adding several matching scores of 89
:
Ziggy (97)
Charlie (89)
Echo (89)
Tango (89)
Zoey (89)
Hoover (82)
Harvey (72)
Bob (67)
To track multiple class scores (hinted at in the code), you could add an Id
(1,2,3) or Code
("101", "201", "303") to the class to qualify which class, series or set each User-Score belongs. Use an additional .Where()
above to get just a subset of the master list.
Finally, rather than storing score sets to individual files, the entire list in its current state can be serialized and saved in 3 or 4 lines of code.
Strings do not contain numbers, nor Dates . They are text.
Don't store individual data elements as one, if you want to use them individually.
What you have is a essentially a multidimensional array containing multiple data types (but in your case, you have concatenated each row into a single string). There isn't a catch-all way to handle this situation, but here are a few methods to consider:
One multidimensional object array:
Dim array(,) As Object = {{"Student1", 95},{"Student2", 87}...}
Two parallel, one dimensional arrays:
Dim names() As String = {"Student1","Student2"...}
Dim scores() As Integer = {95, 87...}
Create a Class or Struct:
Public Class Student
Property name As String
Property score As Integer
End Class
These are all generally better ways of storing your data, but typically put the burden of sorting your data on you. Which leads me to the final option...
Hack together a workaround:
This is essentially what you've already done- concatenated a string with an integer to allow use of the built-in Sort
procedure. You can use the same trick to sort by score, but you have to 0-pad your integers if you want them to sort correctly. See code below, but you've been warned: these type of solutions are invariably easier to implement in the short term but grow unwieldy and less useful in the long term, often needing to be replace by one of the "better" solutions above.
Private Sub FlipStrings(ByRef students() As String)
If students Is Nothing Then Exit Sub
For i As Integer = 0 To UBound(students)
Dim parts() As String = Split(students(i))
If parts Is Nothing OrElse UBound(parts) <> 1 Then Continue For
If IsNumeric(parts(0)) Then
students(i) = parts(1) & " " & CInt(parts(0))
ElseIf IsNumeric(parts(1)) Then
Do Until len(parts(1)) = 3 'Assuming max score of 100'
parts(1) = "0" & parts(1)
Loop
students(i) = parts(1) & " " & parts(0)
End If
Next
End Sub
I wrote this so you can still store and display your array exactly as before. Now, to sort by score
FlipStrings(array)
System.Array.Sort(array)
FlipStrings(array)
should give you exactly what you're looking for.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.