Jump to content

Possible _ArrayUnique bug?


Jfish
 Share

Recommended Posts

One more quick data point, I re-ran my test with $iIntType at the default of 0 - but before I called _ArrayUnique I cast all values in the array to strings and it worked whereas before it failed.

@Jos edit crossed with my post ...

Edited by Jfish

Build your own poker game with AutoIt: pokerlogic.au3 | Learn To Program Using FREE Tools with AutoIt

Link to comment
Share on other sites

  • Developers

There is one other issue with _ArrayUnique: 

This line is not retrieving the correct cell when using _ArrayUnique($sourceArray,1)

Local $vFirstElem = ( ($iDims = 1) ? ($aArray[$iBase]) : ($aArray[$iColumn][$iBase]) )

and think it needs to be changed to:

Local $vFirstElem = ( ($iDims = 1) ? ($aArray[$iBase]) : ($aArray[$iBase][$iColumn]) )

To make the test for the first cell work properly.

Jos

Edited by Jos

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

  • Moderators

Jos,

Good spot with the base/column switch - my fault.

I seem to remember a discussion some time ago about IsInt returning True when used on doubles that held integer values - so I agree that we should use VarGetType to detect when a true integer is used:

; Autocheck of first element
If $iIntType = $ARRAYUNIQUE_AUTO Then
    Local $vFirstElem = ( ($iDims = 1) ? ($aArray[$iBase]) : ($aArray[$iBase][$iColumn]) )
    If StringRegExp(VarGetType($vFirstElem), "Int(32|64)") Then
        Switch VarGetType($vFirstElem)
            Case "Int32"
                $iIntType = $ARRAYUNIQUE_FORCE32
            Case "Int64"
                $iIntType = $ARRAYUNIQUE_FORCE64
        EndSwitch

    Else
        $iIntType = $ARRAYUNIQUE_FORCE32
    EndIf
EndIf

Now doubles fall through and we save a couple of lines on your suggested solution above.

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

You can get rid of the RegExp.
 

; Autocheck of first element
If $iIntType = $ARRAYUNIQUE_AUTO Then
    Local $vFirstElem = ( ($iDims = 1) ? $aArray[$iBase] : $aArray[$iBase][$iColumn] )
    If StringInStr(VarGetType($vFirstElem), "Int") Then
        Switch VarGetType($vFirstElem)
            Case "Int32"
                $iIntType = $ARRAYUNIQUE_FORCE32
            Case "Int64"
                $iIntType = $ARRAYUNIQUE_FORCE64
        EndSwitch

    Else
        $iIntType = $ARRAYUNIQUE_FORCE32
    EndIf
EndIf

Edit: and perhaps a couple of parentheses.

Edited by czardas
Link to comment
Share on other sites

I polished @czardas's snippet further:

If $iIntType = $ARRAYUNIQUE_AUTO Then
    Local $vFirstElem = ( ($iDims = 1) ? $aArray[$iBase] : $aArray[$iBase][$iColumn] )
    Switch VarGetType($vFirstElem)
        Case "Int32"
            $iIntType = $ARRAYUNIQUE_FORCE32
        Case "Int64"
            $iIntType = $ARRAYUNIQUE_FORCE64
        Case Else
            $iIntType = $ARRAYUNIQUE_FORCE32
    EndSwitch

Hope its not buggy >_<

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Link to comment
Share on other sites

@TheDcoder Well spotted! :) 

If $iIntType = $ARRAYUNIQUE_AUTO Then
    Local $vFirstElem = ( ($iDims = 1) ? $aArray[$iBase] : $aArray[$iBase][$iColumn] )
    Switch VarGetType($vFirstElem)
        Case "Int64"
            $iIntType = $ARRAYUNIQUE_FORCE64
        Case Else
            $iIntType = $ARRAYUNIQUE_FORCE32
    EndSwitch
EndIf

Edit: I'm a bit confused about the logic though. A float double could be greater than 0x7FFFFFFF, or less than 0x80000000. Perhaps I misunderstand the intention.

Edited by czardas
Link to comment
Share on other sites

@czardas

If $iIntType = $ARRAYUNIQUE_AUTO Then
    Local $vFirstElem = ( ($iDims = 1) ? $aArray[$iBase] : $aArray[$iBase][$iColumn] )
    If VarGetType($vFirstElem) = "Int64" Then
        $iIntType = $ARRAYUNIQUE_FORCE64
    Else
        $iIntType = $ARRAYUNIQUE_FORCE32
    EndIf
EndIf

:>

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Link to comment
Share on other sites

  • Developers

 

now doubles fall through and we save a couple of lines on your suggested solution above.

Just made the change in that way to prove my point and leave it to the others to come up with the best way to code this. (As is clearly demonstrate in the subsequent posts :) )
I mostly find pleasure in solving the "mystery". 

Jos  

 

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

  • Moderators

czardas,

I'm a bit confused about the logic though

Then re-read this thread (private forum).

 M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

I looked at the current implementation. I still don't understand why you only want to test the first element, but the logic of the code is flawed regardless. An integer can be of three types. Conversion of doubles to integer datatypes can have two outcomes: Int-32 or Int-64.

Look at __DoubleTo64() in my operator64 (see sig). It's not a perfect solution, but you should see what I mean.

Edited by czardas
Link to comment
Share on other sites

  • Moderators

czardas,

I still don't understand why you use only want to test the first element

The function cannot cope with every possible case (in a similar fashion to the _FileWritetoLine case we are discussing elsewhere), so the default assumption is made that the elements to be "uniqued" are all of the same datatype. So when the default $ARRAYUNIQUE_AUTO parameter is used, the function looks at the first element to be "uniqued" and determines its datatype. If the element is an Int64 then the function uses the slower algorithm and errors if it finds any Int32 elements - in all other cases it runs the fast algorithm and errors if it finds any Int64 elements. The user can override this by using the other parameters as explained In the Help file. We are forced into having 2 algorithms by the inability of the scripting object to accept Int64 keys and wanting to run the function as fast as possible - the "slow" algorithm being very significantly slower.

If you think this logic is flawed then please do explain why.

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

I added a comment about doubles to my last post. This is the function I mentioned.

; #INTERNAL_USE_ONLY# ==========================================================================================================
; Name...........: __DoubleTo64
; Description ...: Helper function - converts an integer value double to Int-32 or Int-64.
; Syntax.........: __DoubleTo64($nValue)
; Parameters.....; $nValue - The double to convert
; Return values .: Success returns Int-32 or Int-64 when the interpreter evaluates the converted double equal to the input.
;                  Failure returns the input parameter without any modification and sets the following flags:
;                  |@error = 3 Internal error (x2) ==> see comments in the code.
;                  |@extended = 2 Conversion failed ==> the return value is not an integer.
; Author ........: czardas
; Comments ......; Doubles representing integer values greater than 15 digits cannot be relied on for accuracy.
; ==============================================================================================================================

Func __DoubleTo64($nValue)
    If Not IsNumber($nValue) Then Return SetError(3, 2, $nValue) ; the input is not a number.
    If $nValue > -1.0e+015 And $nValue < 1.0e+015 Then
        Local $iVal64 = Number($nValue, 2) ; convert to Int-64
        If $iVal64 = $nValue Then ; check to see if conversion was a success [expected range +/- 5.62949953421311e+014]
            Return ($iVal64 > 2147483647 Or $iVal64 < -2147483648) ? $iVal64 : Number($iVal64, 1) ; Int-64 or Int-32
        ElseIf $iVal64 -1 = $nValue Then ; attempt to adjust for inaccuracies [subject to possible change]
            Return $iVal64 -1
        ElseIf $iVal64 +1 = $nValue Then ; as above
            Return $iVal64 +1
        EndIf
    EndIf

    Return SetError(3, 2, $nValue) ; conversion failed
EndFunc ;==> __DoubleTo64

If you automatically assume Int-32 for an integer that is not Int-64, I guess it will max out on a large percentage of doubles.

Edited by czardas
Link to comment
Share on other sites

  • Moderators

czardas,

There has to be a balance between user convenience and the function's ability to cover every possible edge case. As the Help file explains, if the user knows (or even suspects) that there are large double values involved then they can set the $iIntType parameter to use the slower algorithm and thus not force any integer-value doubles into Int32. Getting the function to check every element in an attempt to determine the correct fashion to deal with the contents of an array will make it even slower than it already is.

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

I haven't used the scripting object method, so I will take your word for it. My suggested corrections to that line would be:

If $iIntType = $ARRAYUNIQUE_AUTO Then
    Local $vFirstElem = ( ($iDims = 1) ? $aArray[$iBase] : $aArray[$iBase][$iColumn] )
    If VarGetType($vFirstElem) = "Int64" Or $vFirstElem > 0x7FFFFFFF Or $vFirstElem < 0x80000000 Then
        $iIntType = $ARRAYUNIQUE_FORCE64
    Else
        $iIntType = $ARRAYUNIQUE_FORCE32
    EndIf
EndIf

This shouldn't add any significant delay, other than when it is actually needed (but it's obviously not foolproof).

Edited by czardas
Link to comment
Share on other sites

I'd make it do as little as possible to produce the desired results and leave the edge cases to the person writing their script to overcome the limitations. There seems to be a function inflation in regards to every UDF these days that just shouldn't be done. They're used as a library function, they shouldn't be customized to every user's whim. Get them, the included UDFs, doing the basics, and leave the inflation to the user's to devise their own functions.

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

Large integer doubles are not exactly what I would call edge cases. As soon as you use the division operator, you get a double. That being said, I agree that a compromise has to be made somewhere. Recursively looping through multidimensional arrays contained within the elements of other arrays to test all elements within a main (non-unique) array would be taking things way too far IMO.

Edited by czardas
Link to comment
Share on other sites

My comment wasn't referencing yours, its in reference to the whole thread heading towards the function being redone to accommodate the oddest of cases instead of leaving it alone and letting it do what it's supposed to do with the standard functionality. As I said, let the edge cases be handled by the person writing the script if they want it, library functions shouldn't be handling EVERY possible possibility.

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...