【问题标题】:Implementing a function similar to EXCEL Lookup in VB.net在VB.net中实现一个类似于EXCEL Lookup的功能
【发布时间】:2017-07-09 02:00:05
【问题描述】:

我有很多代码需要生成随机数,然后根据百分比选择选项。我只需使用 Mersenne Twister 的实现并在 0 到 100 之间生成一个双精度数,然后使用选择案例按百分比分配结果,就可以毫无问题地工作。它工作得很好,但它很麻烦,说实话,我厌倦了每次都不断地写出来。

我更喜欢类似于 EXCEL 的查找函数的东西,您可以在其中提供两个数组,例如 LOOKUP(5, {1,10,20,30,40}, {"1-10", "11-20", "21-30","31-40"})

在这种情况下会返回:“1-10”,因为 5 介于 1-10 之间。

是否有一种使用 LINQ 实现 C#/VB.Net 版本的简单方法?我确定必须有,但我不知道如何实施这样的事情。编写这一行代码比长的 select case 语句要容易得多。

如果有比实现等效的 EXCEL 查找函数更好的方法,我也很想知道...

【问题讨论】:

    标签: c# vb.net linq lookup


    【解决方案1】:

    我假设您正在执行第二种形式的查找,因为如果第一个参数与第二个参数中传递的数组中的元素不完全匹配,第一种会引发错误。

    这应该可行:

    Public Function LookUp(Of T)(ByVal value As IComparable, ByVal Values() As IComparable, ByVal Result() As T) As Object
        If Values Is Nothing Then Throw New ArgumentException("Values cannot be nothing")
        If Values.Length = 0 Then Throw New ArgumentException("Values can not be empty")
        If Result Is Nothing Then Throw New ArgumentException("Result cannot be nothing")
        If Values.Length = 0 Then Throw New ArgumentException("Result can not be empty")
        If Values.Length <> Result.Length Then Throw New ArgumentException("Values and Result must have the same length")
        Dim i As Integer = 0
        While i < Values.Length AndAlso value.CompareTo(Values(i)) < 0
            i += 1
        End While
        if i = Values.Length Then i-=1
        Return Result(i)
    End Function
    

    用法:

    Dim Result as string = LOOKUP(5, {1,10,20,30,40}, {"1-10", "11-20", "21-30","31-40"})
    

    【讨论】:

      【解决方案2】:

      使用 LINQ 或 Array/List .FindIndex 的方法很少,但整数除法可能是最好的:

      Dim d = 10.1, a = {1, 10, 20, 30, 40}, b = {"1-10", "11-20", "21-30", "31-40"}
      
      Dim s1 = b(a.Count(Function(i) i <= d) - 1)
      
      Dim s2 = b(Array.FindLastIndex(a, Function(i) i <= d))
      
      Dim s3 = $"{d - d Mod 10 + 1}-{d - d Mod 10 + 10}"      ' "11-20"
      

      【讨论】:

      • 好的,所以这适用于使用整数的 1% 的情况。当我使用这样的双精度时,99% 的情况会发生什么:{1.5675, 6.54534, 9.87812, 32.87899, 88.3434,100.1}?我几乎永远不会设计适合“单一案例”场景的东西。我设计的所有东西都必须适用于所有情况。
      • @MattE 您可以根据需要调整它,具体取决于例如从 10 到 11 或小于 1 的值的结果。对于低于 1 或的值,前 2 个将失败40及以上
      【解决方案3】:

      实际上,在我坐在那里思考了几分钟后,我自己想出了类似于@Alexander Higgins 的答案。我这样称呼它:

      CaseLookup({41, 59, 80, 101}, {"Balanced", "PowerBack", "Receiving", "OneCut"}, 0, 100) 
      

      基本上我为下一项设置边界并循环查找它小于的第一个索引,这意味着它会落在该范围内。然后,我只需从查找数组中获取相同的索引作为值。

      Public Shared Function CaseLookup(numArray As Array, lookupArray As Array, minVal As Double, maxval As Double) As String
              Dim result As String = ""
              Dim GetNum As Double = MT.GenerateDouble(minVal, maxval)
      
              If numArray.Length <> lookupArray.Length Then 'Checks to make sure the arrays are the same length
                 Throw New Exception("numArray and lookupArray MUST be the same length!")
                 Exit Function
              End If
      
              For i = 0 To numArray.Length - 1
                  If GetNum < numArray(i) Then result = lookupArray(i).ToString()
              Next i
              Return result
          End Function
      

      【讨论】:

        猜你喜欢
        • 2012-12-19
        • 2017-05-21
        • 1970-01-01
        • 2021-07-08
        • 1970-01-01
        • 2017-07-05
        • 2011-05-29
        • 2016-11-20
        • 1970-01-01
        相关资源
        最近更新 更多