• Can this Lotusscript function be improved?

    By David Jeyachandran 1 decade ago

    Hi,



    Just thought I'd get your thoughts on this…

    I need a way to compare two variants and performance is important. It needs to compare anything a variant can hold eg - text, date, number, multi-value or single value. Do you have a simpler, faster and more robust function or can you improve this one (pasted below)? I've also posted this on:

    http://www-10.lotus.com/ldd/nd6forum.nsf/DateAllThreadedweb/02f091302e1b90b0852575f900102c9f?OpenDocument



    I thought I'd ask the community because I previously thought that the fastest way to compare two variants was to do the following. Concatenate them both variants into single text values and then apply the HashPassword before comparing them. When I ran performance comparisons between a simple comparison (pasted below) and my complicated hashpassword method I found the simple method was often about 30% faster. Can this be improved further or is there an even simpler way of achieving this? Thanks.







    Function isVariantEqual( varValue1 As Variant, varValue2 As Variant ) As Boolean

    'Checks if the Variants are equal - have the same values in the same order.

    'Non-scalar variants with only a single value are treated like a scalar eg. varValue1(0)="text" is equal to varValue2="text"



    Dim isEqualTemp As Boolean



    isEqualTemp=False



    'Check if the first value is scalar

    If Isscalar( varValue1 ) Then

    If Isscalar( varValue2) Then

    If varValue1 = varValue2 Then isEqualTemp=True

    Else

    If Ubound(varValue2)=0 Then

    If varValue1 = varValue2(0) Then isEqualTemp=True

    End If

    End If



    Elseif Isscalar( varValue2 ) Then

    'if the second value is scalar but not the first



    If Ubound(varValue1)=0 Then

    If varValue1(0) = varValue2 Then isEqualTemp=True

    End If





    Else

    'Compare the two arrays

    If isArrayEqual( varValue1, varValue2) Then isEqualTemp=True



    End If



    isVariantEqual = isEqualTemp



    End Function







    Private Function isArrayEqual( varValue1 As Variant, varValue2 As Variant ) As Boolean

    'Is the array equal both insize, values and order



    Dim isEqualTemp As Boolean

    Dim i As Integer, intArraySize2 As Integer



    'If the arrays have the same Ubound then cycle through each element till one mismatches

    intArraySize2=Ubound(varValue2)

    If Ubound(varValue1)=intArraySize2 Then



    i=0

    isEqualTemp = True

    While isEqualTemp And i<=intArraySize2

    If varValue1(i)<>varValue2(i) Then isEqualTemp=False

    i=i+1

    Wend



    Else

    isEqualTemp=False

    End If



    isArrayEqual = isEqualTemp



    End Function

    • Fast equality-Function

      By Holger Chudek 1 decade ago

      Hi,



      what is your definition for equality ?? ist the List a:b:c equal to a:c:b or not (so do the elements have to be in the same order ?)



      if not, there is a function on the following website :



      http://www.breakingpar.com/bkp/home.nsf/0/87256B280015193F87256BEB0053DAEE



      if order does matter, i came to one initial stage for a solution :



      in the first pass, the first Array has to be stored in a list (hashList), the key should be a hash-representation of the value and the listvalue should be the index (the Hash should be an own function to calculate the hashvalue depending on the datatype).



      Something like



      for i = 0 to ubound firstArray

      hashList(hash(firstArray(i)) = i

      end forall



      in the second pass iterate over all elements of the second array, build the hash

      and look for the elemnt in the list (isElement(seekValrayValue))), if not found, arrays are not equal, you can skip if found, get the Value from the list and look if it is equal to the actual index



      arraysAreEqual = true

      for j = 0 to ubound secondArray

      hashVal = hash(secondArray(j))

      if not isElement(hashVal) then

      arrayAreEqual = false

      exit forall

      endIf



      if not hashList(hashVal) = j then

      arrayAreEqual = false

      exit forall

      endIf



      end forall



      Surely one has to do the Code and has to do the performance tests to know it for sure. And surely it will depend on the numbers of elemnt, which function performs better. And one has to use a performant hash-Function to get the speed.



      Hope this was a help,



      sincerly



      Holger

      • By Holger Chudek 1 decade ago

        Hi,



        now, i had some time to think it over(the last evening).



        For the comparison, you have to touch each value in each array at least once. Even doing a Split(Array) will touch each value internally once and so concatentating the Values to one string will be nearly same time as running through the indices.



        Getting a Value in an Array by index is as fast as getting an Value by key in a list, so we dont need the list in my first posting to do the comparison. And both Values/Arrays are allready in Memory. So the most consuming time will be the comparison of the two values and this will be the bottleneck. Creating a password-Hash for the concatenated values and compare them will then be in most cases more time consuming than comparing them directly (it depends on the complexity of the values, shure)



        so if the equality is a:b:c is eqal to a:b:c and not equal to a:c:b, the easiest will be :



        checkEquality = true

        for i = 0 to ubound(firstArray)

        if not isequal(firstArray, secondArray, i) then

        checkEquality = false

        exit forall

        end if

        end forall



        function isEqual(fArr as Variant, sArr as Variant, indx as integer) as integer

        isEqual = false

        fVal = fArr(i)

        sVal = sArr(i)

        if not datatype(fVal) = datatype(fVal) then exit function

        select case datatype(fVal)

        case "String" : Comparison for String-Values

        case "integer" : Comparison for Integer-Values

        ….



        One has to do the main checks (number of Elements are equal, both are Arrays) before doing the

        comparison-Function, but with such a function one will be able to change the comparison-functionality

        withot changing the rest of the code, even odd comparisons (eg, integer 1 will be eqal to string "A" are then possible by doing some exeptions in the equality-Function



        And you can tune the performance for the comparison according to the needs, for example you wont have to convert all values to string, hence they are allready all in integer.



        Hope , my thougts are not to crude

        with kind regards,

        Holger




        • Great Stuff!

          By David Jeyachandran 1 decade ago

          Hi Holger,



          Thank you for that. I'll now be running some tests on this. Olli has also provided good ideas and has helped with the testing. I will let you know the results.



          Thanks & Regards

          David