繁体   English   中英

如何在DataTable的一行中将多个列引用为二维数组?

[英]how can I reference multiple columns in a single row within a DataTable as a two-dimensional array?

基本问题是如何在DataTable的一行中将多个连续列引用为可以使用For-Next结构进行处理的二维数组? 这是背景:

所涉及的程序从.csv文件加载数据,其中每行/每行包含有关某人的基本身份信息,其后为对两个问题的数字答案。 程序在.csv文件的每一行中循环,并标识出与当前行的确切答案匹配次数最高的其他五行。

DataTable似乎是将.csv文件读入的最佳结构,但是不确定如何将每一行的最后x列作为答案(人,问题)的数组引用。

万一这看起来真的很简单或完全不切实际,我应该声明以下内容:程序代码已经编写并且可以运行,但是我正在从QuickBASIC 4重新编码它(是的,我确实说过QB4。 ..)到VB.NET。 该程序基本上是一个约会程序,在过去的20多年中,我每年都运行一次,本地学校以筹款的形式出售火柴。 到Windows 7或Windows XP的最新修补程序版本都无法运行QB4的地步,所以我下载了VS Express for Desktop,并将其作为学习VB.NET的机会。 我已经做过很多(非窗口式的)VBScript应用程序脚本,但是我对传统VB的唯一经验是对VB6的一些浅尝light止。 众所周知,.NET中的文件I / O与VB6或更早的版本完全不同。 那就是我现在正在战斗的……

.....

要回答Zohar的问题/评论:
下面是.csv文件格式的示例。 实际文件的长度为几百行,但格式完全相同。 为了保护隐私,姓名和电话号码已更改。 字段依次为:


名字
电话号码(如果提供,则使用占位符,否则)
性别(1 = M; 2 = F)
对问题1(1-4)的回答
对问题2(1-4)的回答
....
对问题24(1-4)的回答

Mouse,Mickey,xxx-xxxx,1,2,3,3,2,3,1,3,4,2,1,4,3,1,1,2,1,2,1,1,1,2,1,1,4
Mouse,Minnie,555-9931,2,1,3,1,2,1,2,3,3,3,4,4,2,4,1,2,3,4,4,4,1,2,1,1,4
Duck,Donald,555-7024,1,2,3,4,2,4,3,4,2,2,1,4,2,4,1,2,1,1,2,1,3,2,1,1,1
McDuck,Scrooge,555-4824,1,2,3,3,2,1,2,4,3,2,4,4,2,4,1,4,2,2,4,4,3,2,1,1,4
GoodWitch,Wendy,xxx-xxxx,2,2,2,4,2,1,2,4,4,3,4,2,2,1,1,2,1,1,4,4,4,4,1,3,1

二维数组的原因是创建一个按用户和问题编号回答的单变量数据库。 有关实际现有QB4代码的排序部分,请参见下文。 我要带入VB.NET标准的二维数组是StudentAnswer(matchFrom,问题)。

    For matchFrom = 1 To numberSheets
        '
        'The following section of code finds the top maximumToMatch groups of n
        'matching questions per sheet
        '
        For x = 1 To maximumToMatch
            topMatches(x) = 0
            sheetsMatched(x) = 0
        Next x
        For matchTo = 1 To numberSheets
            If StudentSex(matchFrom) <> StudentSex(matchTo) Then
                numberMatched(matchTo) = 0
                highMatch = 0
                For question = 1 To numberQuestions
                    If StudentAnswer(matchFrom, question) = StudentAnswer(matchTo, question) Then
                        numberMatched(matchTo) = numberMatched(matchTo) + 1
                    End If
                Next question
                If numberMatched(matchTo) = topMatches(1) Then
                    sheetsMatched(1) = sheetsMatched(1) + 1
                End If
                If numberMatched(matchTo) > topMatches(1) Then
                    match = maximumToMatch
                    done = False
                    Do
                        If numberMatched(matchTo) = topMatches(match) Then
                            sheetsMatched(match) = sheetsMatched(match) + 1
                            done = True
                        End If
                        If numberMatched(matchTo) > topMatches(match) Then
                            For x = 1 To match - 1
                                topMatches(x) = topMatches(x + 1)
                                sheetsMatched(x) = sheetsMatched(x + 1)
                            Next x
                            topMatches(match) = numberMatched(matchTo)
                            sheetsMatched(match) = 1
                            done = True
                        Else
                            match = match - 1
                        End If
                    Loop Until done
                End If
            Else
                numberMatched(matchTo) = 0
            End If
        Next matchTo
    ...
    <additional code to narrow it down to a fixed number of sheet matches>
    Next matchFrom

并预期另外两个可能的问题:

编写现有代码以使M与F匹配,反之亦然。 我想在重写过程中使它更加灵活,但这是农村地区,我不确定他们是否已经为此做好了准备...

数据文件为.csv格式的原因是缺少为程序编写的正式数据输入前端。 这一直在待办事项列表上,但是与此同时,由于它每年只运行一次,因此Excel一直是我的朋友...如果一切顺利,我将在VB.NET re期间设计一个数据输入屏幕-写。

在此先感谢所有抽出宝贵时间阅读本文的人。

现在可以使用LINQ(因为.NET 3.5,所以不是新的)来查询对象列表,使用DataTable可能不是最佳选择,因为数据来自CSV文件而不是数据库(也可以使用LINQ)用于数据库)。

因此,这实际上不是您原始问题的答案,但是如果您输入了以下内容:

Joe User,1,2,3,4,5
Jane User,2,2,3,4,6
Jack User,3,4,5,2,8
Jill User,5,3,1,8,6

您可以定义一个类来存储数据:

Public Class UserInfo
    Public Property Name As String
    Public Property Answers As List(Of Integer) = New List(Of Integer)()
    Public Function MatchRating(other As UserInfo) As Integer
        Dim rating As Integer = 0
        For i = 0 To Me.Answers.Count - 1
            If Me.Answers(i) = other.Answers(i) Then
                rating += 1
            End If
        Next
        Return rating
    End Function
End Class

然后,您可以将CSV数据读入UserInfo对象的列表:

    Dim users = File.ReadLines("Data.csv").Select(
        Function(line)
            Dim parts = line.Split(","c)
            Dim user = New UserInfo() With {.Name = parts(0)}
            user.Answers.AddRange(parts.Skip(1).Select(Function(str) CInt(str)))
            Return user
        End Function
    ).ToList()

然后,您可以找到类似以下内容的最佳匹配项,该匹配项循环遍历用户并使用LINQ查询根据匹配的答案数( UserInfo.MatchRating函数)找到前5个匹配项,并跳过所有不匹配的匹配项( rating > 0 ):

    For Each user In users
        Console.WriteLine("{0}:{1}", user.Name, String.Join(",", user.Answers))
        Dim bestMatches = From u In users
                          Where u IsNot user
                          Let rating = u.MatchRating(user)
                          Where rating > 0
                          Order By rating Descending
                          Take 5
                          Select New With {.Name = u.Name, .Rating = rating}
        For Each match In bestMatches
            Console.WriteLine("  Match: {0}, rating: {1}", match.Name, match.Rating)
        Next
    Next

您需要将属性添加到UserInfo类的真实身份信息,并调整代码相匹配。

您还需要确保正确设置了项目选项,并且需要适当的导入/引用,例如:

Option Explicit On
Option Infer On
Option Strict On

Imports System.IO

作为参考,我的测试结果为(杰克可怜,我想您可能需要针对性偏好进行调整,例如Where u IsNot user AndAlso u.Sex <> user.Sex ):

Joe User:1,2,3,4,5
  Match: Jane User, rating: 3
Jane User:2,2,3,4,6
  Match: Joe User, rating: 3
  Match: Jill User, rating: 1
Jack User:3,4,5,2,8
Jill User:5,3,1,8,6
  Match: Jane User, rating: 1

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM