【问题标题】:Setting string a variable to get values from a structured array设置字符串变量以从结构化数组中获取值
【发布时间】:2021-08-29 02:25:30
【问题描述】:

我在 VB.net 中有一个简单的问题。 我想使用字符串从声明为结构的数组中检索数据以可视化变量。 在我的代码下面:

Module DataAnalisys

Dim InputData(100000) As InputDataStructure
Dim VariablesParameter(6) As VariablesParameterStructure
Dim VariablesGlobal(6) As VariablesDataStrucutre

Structure InputDataStructure
    Dim ID As Integer
    Dim FileId As Integer
    Dim ProductionDate As Date
    Dim ProductionTime As Date
    Dim Shift As Integer
    Dim IPP As Integer
    Dim BPS As Integer
    Dim SerialNumber As String
    Dim Top As Single
    Dim Bottom As Single
    Dim Right As Single
    Dim Left As Single
    Dim OffCutH As Single
    Dim OffCutV As Single
    Dim Row As Byte
    Dim Col As String
    Dim Position As String
    Dim Pack As Integer
    Dim Sheet As Integer
    Dim SheetInPack As Integer
End Structure

Structure VariablesParameterStructure
    Dim NameParameter As String
    Dim Target As Single
    Dim Tolerance As Single
    Dim LowTolerance As Single
    Dim UppTolerance As Single
End Structure

Structure VariablesDataStrucutre
    Dim NameData As String
    Dim Position As String
    Dim N As Long
    Dim Mean As Single
    Dim Difference As Single
    Dim Scrap As Single
    Dim ScrapGreat As Single
    Dim ScrapLess As Single
    Dim SeMean As Single
    Dim StDev As Single
    Dim Min As Single
    Dim Q1 As Single
    Dim Median As Single
    Dim Q3 As Single
    Dim Max As Single
End Structure

Sub RoutineAnalisysGlobal()

    For B As Byte = 0 To VariablesGlobal.Length - 1

        Dim ID As String = VariablesParameter(B).NameParameter
        Dim Target As Single = VariablesParameter(B).Target
        Dim LowTol As Single = VariablesParameter(B).LowTolerance
        Dim UppTol As Single = VariablesParameter(B).UppTolerance

        With VariablesGlobal(B)
            .NameData = ID
            .Position = "All"
            .N = InputData.Length
            .Mean = InputData.Average(Function(f) f.ID)
            .Difference = .Mean - Target
            .ScrapLess = InputData.Count(Function(f) f.ID < LowTol)
            .ScrapGreat = InputData.Count(Function(f) f.ID > UppTol)
            .Q1 = InputData.FirstQuartile(Function(F) F.ID)
            .Min = InputData.Min(Function(f) f.ID)
            .Median = InputdataMedian(Function(f) f.ID)
            .Q3 = InputData.ThirdQuartile(Function(f) f.ID)
            .Max = InputData.Max(Function(f) f.ID)
        End With
    Next

End Sub

End Module

VariablesParameter().Name 是 Top、Bottom、Right、Left、OffCutH 和 OffCutV。

当我使用部分 (Function(f) f.ID) 时代码不起作用,因为我想根据 for 循环在 InputData 结构的不同项目上使用该函数。我想显示 f.Top f.Bottom f.Right f.Left f.OffCutH 和 f.OffCutV。

有人想帮助我吗?我正在研究如何将字符串 ID 转换为 InputData 的变量。??????结构。

【问题讨论】:

  • 这到底应该做什么:.Mean = InputData.Average(Function(f) f.ID)?就目前而言,您得到了所有 ID 值的平均值,这似乎没有意义。我怀疑您真正想要的是获取所有元素的其他字段的平均值,其中 ID 等于某个特定值。那是对的吗?如果是这样,那么您需要先调用 Where 来过滤数据,然后调用 Average 并指定要获取平均值的字段,例如.Mean = InputData.Where(Function(f) f.ID = ID).Average(Function(f) f.Top).
  • @jmcilhinney 可能 ID 具有误导性,因为它在代码中出现了两次。我想做一个非常简单的事情,例如以下 6 个平均值:InputData.Average(Function(f) f.Top) - InputData.Average(Function(f) f.Bottom) - InputData.Average(Function(f) f.Right) - InputData.Average(Function(f) f.Left) - InputData.Average(Function(f) f.OffCutHTop) - InputData.Average(Function(f) f.OffCutV) 但我不知道如何更改为f.Top, f.Bottom, f.Right, f.Left, f.OffCutH and f.OffCutV之间的for循环
  • 看起来好像您想要具有 6 个元素的数组,因为您正在谈论平均 6 个字段。如果是这种情况,那么您创建数组的方式,例如Dim VariablesParameter(6) As VariablesParameterStructure,错了。这将创建一个包含 7 个元素的数组。在VB中创建数组时指定上限,比长度小1。
  • 您的代码中还有一些拼写错误。您在两个地方有“Analisys”而不是“Analysis”,在一个地方有“Strucutre”而不是“Structure”。您还必须拥有Option Strict Off 才能编译该代码,这很糟糕。为什么您认为在For 循环中使用Byte 来索引数组是个好主意?索引总是Integers。将此项目转为Option Strict On,并将其设置为所有项目的 VS 选项中的默认值,并帮助您停止编写糟糕的代码。

标签: arrays vb.net structure


【解决方案1】:

我认为您正在寻找的是这样的:

Dim functions As Func(Of InputDataStructure, Single)() = {Function(ids) ids.Top,
                                                          Function(ids) ids.Bottom,
                                                          Function(ids) ids.Right,
                                                          Function(ids) ids.Left,
                                                          Function(ids) ids.OffCutH,
                                                          Function(ids) ids.OffCutV}

For i = 0 To VariablesGlobal.GetUpperBound(0)
    With VariablesGlobal(i)
        '...
        .Mean = InputData.Average(functions(i))
        '...
    End With
Next

作为解释,这行的Function(f) f.ID 部分:

.Mean = InputData.Average(Function(f) f.ID)

是一个 lambda 表达式,即匿名方法的委托。您正在调用的Average 方法需要一个具有T 类型的单个参数的方法的委托,其中T 匹配您正在调用它的IEnumerable(Of T) 的泛型类型,并返回数值类型的值,例如IntegerSingle。在您的情况下,您在InputData 上调用Average,它实现了IEnumerable(Of InputDataStructure)。您的 lambda 表达式有一个 InputDataStructure 类型的参数并返回一个 Integer,因此它适用于 AverageAverage 方法为列表中的每个项目调用该委托,获取所有数字结果,然后将其除以列表中的项目数以获得平均值。

为了更清楚那里发生的事情,您可以使用命名方法而不是 lambda 表达式。你可以写这个方法:

Private Function GetID(f As InputDataStructure) As Integer
    Return f.ID
End Function

然后将您的代码更改为:

.Mean = InputData.Average(AddressOf GetID)

希望您能识别出该命名方法中与 lambda 表达式相对应的部分以及推断出的部分。

现在,您有许多使用相同 lambda 表达式的代码行,例如

.Min = InputData.Min(Function(f) f.ID)
.Median = InputdataMedian(Function(f) f.ID)
.Q3 = InputData.ThirdQuartile(Function(f) f.ID)

对于如此简单的事情,习惯性地按照自己的方式去做。但是,您确实可以选择编写一次 lambda 表达式,将其分配给一个变量,然后多次使用该变量。你可以这样做:

Dim f As Func(Of InputDataStructure, Integer) = Function(ids) ids.ID

或者这个:

Dim f = Function(ids As InputDataStructure) ids.ID

以变量f 结束,该变量引用了一个接受InputDataStructure 类型参数并返回Integer 类型值的委托。然后,您可以在之前使用多个 lambda 表达式的地方使用该变量:

.Min = InputData.Min(f)
.Median = InputdataMedian(f)
.Q3 = InputData.ThirdQuartile(f)

所以,既然我们确定您所需要的只是一个方法的委托,该方法接受正确类型的参数并返回正确类型,请再看看我发布的代码。它首先创建一个包含六个委托的数组,每个委托接受一个InputDataStructure 类型的参数并返回一个Single 类型的值。然后,您可以在需要此类委托的任何地方使用该数组的元素。

这意味着您可以遍历该数组并将每个委托传递给所有期望此类委托的扩展方法,包括Average。如果您在索引 0 处获得委托,那么您将获得返回 Top 属性值的委托,因此 Average 将获得平均 Top 值。如果您使用索引 5,那么您将获得返回 OffCutV 属性值的委托,因此 Average 将获得平均 OffCutV 值。等等。

作为记录,我建议在 lambdas 中使用指示类型的参数名称。您使用了f,但这毫无意义。参数类型为InputDataStructure,所以ids 表示这一点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-06
    • 1970-01-01
    • 1970-01-01
    • 2021-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多