簡體   English   中英

使用字符串和整數對數組進行數字排序

[英]Sort array numerically, with strings and integers

我有一個數組,數組旁邊有一個名稱和一個分數,我需要將其從高到低排序。 我已經按字母順序對其進行了排序。

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

我需要稱為數組的數組進行數字排序。 我將為用戶添加選項,以便用戶按字母順序選擇是否要進一步排序。

字符串不是數字。 它們是文本。

在字符串格式中,它們只是字符( 數字 ),它們不是也不 將按數字排序:

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

輸出:

5 + 07 = 507
9 899 5 42 3 178 07

值未按預期添加,因為它們不是數字。 取而代之的是,代碼僅將字符串的兩位連接在一起(粘合在一起)。 數組內容也按字符排序。 排序時, "9"將始終被視為大於其他值。

這也適用於以字符串形式存儲的日期。 “ 9/16/1914”將始終大於/晚於“ 12/1/2015”。

為什么

因為作為文本,所以按字典順序或字母順序使用(0,1,2,3,4,5,6,7,8,9)。

數字以字符串形式存儲,失去其數值(直到轉換)。 "9"高於種"899" ,因為"9" 高於 "899" “ Able”和“ Baker”將基於“ A”和“ B”進行排序的方式相同。 由於zed, "07"排序最低。 數值被忽略,因為它們是字符串(文本)。

字符串“ dates”也是如此-它們不是日期,也沒有日期值。 您的大腦會根據模式將它們解釋為日期。 在計算機上,它們仍然是文本,並且"9/16/yyyy"計算結果將大於"12/1/yyyy"

使用字符串和整數對數組進行數字排序

現在我們知道字符串數組中沒有整數,只有數字。 但是,如果您有2個數據,則要單獨使用它們,則需要分別存儲它們。 類是理想的選擇:

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

請注意,名稱和分數存儲為正確的數據類型,這將使​​代碼將分數用作數字值。 與使用2個數組不同,該名稱不能與樂譜分離。

還請注意, ToString()允許我們根據需要顯示數據。 僅僅因為我們想顯示名稱和分數並不意味着我們必須將這些信息粘合在一起。 樣本輸出:

查理(89)

學生容器

放棄您的數組(和ArrayList)! 這是21世紀,我們有Typed集合(稱為Generics ):

Private Students As List(of Student)       ' declaration

Students是一個只能存儲Student對象的集合,而Student對象又包含2個數據。 讓我們添加一些:

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))

請注意,我們不必設置List(of Student)的大小-它會根據需要增加。 您仍然可以按元素/位置引用它們: Students(0)Student對象, Students(0).Name將是第一個位置(“ Harvey”)中學生的名稱。

排序

Students = Students.OrderByDescending(Function(x) x.Score).ToList()

這將以所需順序創建一個新集合。 按名稱對匹配分數進行排序:

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

加上多個匹配分數89后的結果:

齊吉(97)
查理(89)
回聲(89)
探戈(89)
佐伊(89)
胡佛(82)
哈維(72)
鮑勃(67)

要跟蹤多個班級成績(在代碼中的提示),您可以向班級添加一個Id (1,2,3)或Code (“ 101”,“ 201”,“ 303”)以限定哪個班級,系列或設置每個用戶分數所屬的。 使用上面的其他.Where()僅獲得主列表的一個子集。

最后,與其將分數集存儲到單個文件中,不如將其當前狀態的整個列表序列化並保存為3或4行代碼。

TL;博士

字符串不包含數字,也不包含Dates 它們是文本。

如果要單獨使用單個數據元素,請不要將其存儲為一個。

實際上,您所擁有的是一個包含多種數據類型的多維數組(但在您的情況下,您已將每一行連接到一個字符串中)。 沒有一種萬能的方法來處理這種情況,但是這里有一些需要考慮的方法:

一個多維對象數組:

Dim array(,) As Object = {{"Student1", 95},{"Student2", 87}...}

兩個平行的一維數組:

Dim names() As String = {"Student1","Student2"...}
Dim scores() As Integer = {95, 87...}

創建一個類或結構:

Public Class Student
    Property name As String
    Property score As Integer
End Class

這些通常都是更好的存儲數據的方法,但通常會給您增加對數據進行排序的負擔。 這導致我最終選擇...

共同解決一個變通方法:

本質上,這就是您已經完成的操作-將字符串與整數連接起來,以允許使用內置的Sort過程。 您可以使用相同的技巧按分數排序,但是如果希望整數正確排序,則必須將其0填充。 請參閱下面的代碼,但是您已經得到警告:這類解決方案在短期內始終易於實現,但從長遠來看卻變得笨拙且用處不大,通常需要替換為上面的“更好”的解決方案之一。

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

我寫了這個,所以您仍然可以像以前一樣存儲和顯示數組。 現在,按分數排序

FlipStrings(array)
System.Array.Sort(array)
FlipStrings(array)

應該給您您想要的東西。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM