简体   繁体   English

在VB.net中实现类似于EXCEL查找的功能

[英]Implementing a function similar to EXCEL Lookup in VB.net

I have a lot of code that requires random numbers to be generated and then options selected based on percentage. 我有很多代码,需要生成随机数,然后根据百分比选择选项。 I have it working without issue by simply using an implementation of the Mersenne Twister and generating a double between 0 and 100, then assigning results by percentage with select case. 我只需使用Mersenne Twister的实现并生成0到100之间的双精度,然后按选择大小写按百分比分配结果,就可以毫无问题地工作。 It works fine, but it's very cumbersome and truth be told, I'm tired of continuously writing this out everytime. 它工作正常,但是非常麻烦,说实话,我厌倦了每次都不断写出来的东西。

I'd much prefer something similar to EXCEL's Lookup Function where you give two arrays such as LOOKUP(5, {1,10,20,30,40}, {"1-10", "11-20", "21-30","31-40"}) 我更喜欢类似于EXCEL的Lookup Function的功能,在其中您可以提供两个数组,例如LOOKUP(5, {1,10,20,30,40}, {"1-10", "11-20", "21-30","31-40"})

Which in this case would return: "1-10" since 5 is between 1-10. 在这种情况下它将返回:“ 1-10”,因为5在1-10之间。

Is there an easy way to implement a C#/VB.Net version of this using LINQ? 有没有一种简单的方法可以使用LINQ来实现C#/ VB.Net版本? I'm sure there must be but I'm at a loss for how to implement something like this. 我敢肯定一定有,但是我对如何实现这样的事情迷茫了。 It would be far easier to write this one line of code than long select case statements. 与长选择案例语句相比,编写这一行代码要容易得多。

If there is a better way than implementing an equivalent of an EXCEL lookup function, I'd love to know that as well... 如果有比实现等效的EXCEL查找功能更好的方法,我也很想知道...

I am assuming your are doing the second form of lookup, as the first would throw an error if the first argument doesn't exactly match an element in the array passed in the second argument. 我假设您正在执行第二种形式的查找,因为如果第一个参数与第二个参数中传递的数组中的元素不完全匹配,则第一种将引发错误。

This should work: 这应该工作:

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

Usage: 用法:

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

There are few ways to do it with LINQ or Array/List .FindIndex, but integer division is probably the best: 使用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"

I actually came up with something similar to @Alexander Higgins answer on my own after I sat there and thought about it for a few minutes. 我坐在那里思考了几分钟后,实际上自己想到了类似于@Alexander Higgins的答案。 I call it like so: 我这样称呼它:

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

Basically I set the boundary for the next item and loop to find the first index it is less than, which means it would fall within that range. 基本上,我为下一项设置边界并循环查找小于的第一个索引,这意味着它将落在该范围内。 I then simply take the same index from the lookup array as the value. 然后,我简单地从查找数组中获取与值相同的索引。

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

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

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