使用字符串和整数以数字方式对数组进行排序

时间:2015-07-03 13:46:50

标签: arrays vb.net sorting

我有一个数组,旁边有一个名字和一个分数,我需要它从高到低排序。我已经按字母顺序排序了。

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

我需要在数字上对数组进行排序。我将为用户添加选项,以便在按字母顺序完成后选择是否要进一步排序。

2 个答案:

答案 0 :(得分:1)

字符串不是数字。它们是文本。

在字符串格式中,它们只是字符(数字),而不会按数字排序:

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”。

为什么

因为作为文本,使用了lexicographical或字母顺序(0,1,2,3,4,5,6,7,8,9)。

以字符串形式存储,数字会松散其数值(直到转换为止)。 "9"排序高于"899",因为"9" 高于"899"。与“Able”和“Baker”基于“A”和“B”排序的方式相同。由于zed,"07"排序最低。 忽略数值,因为它们是字符串(文本)。

字符串“日期”也是如此 - 它们不是日期,也没有日期值。你的大脑根据模式将它们解释为日期;对于计算机,它们仍为文本,"9/16/yyyy"的评估大于"12/1/yyyy"

使用字符串和整数以数字方式对数组进行排序

我们现在知道字符串数组中没有整数,只有数字。但是,如果您有2个数据,如果您想单独使用,则需要单独存储它们。 Class是理想的:

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)

学生容器

放弃你的数组(和ArrayLists)!这是21世纪,我们有类型的集合(称为Generics):

Private Students As List(of Student)       ' declaration

Students是一个只能存储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后的结果:

  

Ziggy(97)
  查理(89)
  回声(89)
  探戈(89)
  佐伊(89)
  胡佛(82)
  哈维(72)
  鲍勃(67)

要跟踪多个课程分数(在代码中暗示),您可以添加Id(1,2,3)或Code(“101”,“201”,“303” )到班级,以确定每个用户分数属于哪个类,系列或设置。使用上面的其他.Where()来获取主列表的一部分。

最后,不是将得分集存储到单个文件中,而是将当前状态的整个列表序列化并保存在3行或4行代码中。

TL;博士

字符串不包含数字,也不包含日期。它们是文字。

如果您想单独使用它们,请不要将各个数据元素存储为一个。

答案 1 :(得分:0)

你所拥有的本质上是一个包含多种数据类型的多维数组(但在你的情况下,你已经将每一行连接成一个字符串)。处理这种情况并不是一种全能的方式,但这里有几种方法需要考虑:

一个多维对象数组:

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填充。请参阅下面的代码,但您已经收到警告:这些类型的解决方案总是在短期内更容易实施,但从长远来看变得笨拙且不太有用,通常需要替换其中一个解决方案。更好&#34;以上解决方案。

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)

应该准确地告诉你你正在寻找的东西。